見出し画像

TWSNMP開発日誌:モバイル版のユニットテストでつまずく

浦和レッズ 残念!
連続引き分けから脱出したので次は勝つだけと思います。

さて、今朝は4時から昨日作ったモバイル版のノード情報を保存するソースコードを改善してテストプログラムも書いてみました。1時間ほどでできました。
テストプログラムを動かしてみると

テストとは関係ないところで例外発生して失敗しました。
2時間ほど、いろいろ調べましたがわかりません。
試しに例外の発生する関数を呼ぶところをコメントにしてテストを実行すると

テストは成功しました。
改善したコードは、

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert';
import 'package:hooks_riverpod/hooks_riverpod.dart';

class Node {
  String name;
  String ip;
  String snmpMode;
  String community;
  String user;
  String password;
  String icon;

  Node({
    this.name = '',
    this.ip = '',
    this.snmpMode = '',
    this.community = '',
    this.user = '',
    this.password = '',
    this.icon = '',
  });

  /// Map型に変換
  Map toMap() => {
        'name': name,
        'ip': ip,
        'snmpMode': snmpMode,
        'community': community,
        'user': user,
        'password': password,
        'icon': icon,
      };

  /// JSONオブジェクトを代入
  Node.fromMap(Map map)
      : name = map['name'],
        ip = map['ip'],
        snmpMode = map['snmpMode'],
        community = map['community'],
        user = map['user'],
        password = map['password'],
        icon = map['icon'];
}

final countViewModel = ChangeNotifierProvider((_) => Nodes());

class Nodes with ChangeNotifier {
  // ノードリスト
  List<Node> nodes = [];

  Nodes() {
    load();
  }

  bool add(Node n) {
    for (var i = 0; i < nodes.length; i++) {
      if (n.ip == nodes[i].ip) {
        return false;
      }
    }
    nodes.add(n);
    return true;
  }

  bool update(int i, Node n) {
    if (i < 0 || i >= nodes.length) {
      return false;
    }
    nodes[i] = n;
    return true;
  }

  bool delete(int i) {
    if (i < 0 || i >= nodes.length) {
      return false;
    }
    nodes.removeAt(i);
    return true;
  }

  /// SharedPrefrences保存
  Future save() async {
    // ①Map型変換→②Json形式にエンコード→③リスト化
    List<String> strNodes = nodes.map((n) => json.encode(n.toMap())).toList();

    SharedPreferences prefs = await SharedPreferences.getInstance();
    // ④保存
    await prefs.setStringList('nodes', strNodes);

    print('updateSharedPrefrences: $strNodes');
  }

  /// SharedPrefrences読み出し
  Future load() async {
    print('syncDataWithProvider');

    SharedPreferences prefs = await SharedPreferences.getInstance();
    // ①読み出し
    var result = prefs.getStringList('nodes');

    print('result:$result');

    // 読み出し確認
    if (result != null) {
      // ②デコード→③MapオブジェクトをClockModelに代入→④リストに変換
      nodes = result.map((f) => Node.fromMap(json.decode(f))).toList();
    } else {
      // 必要に応じて初期化
    }
  }
}

作ったテストコードは、

import 'package:flutter/material.dart';
import 'package:test/test.dart';
import 'package:twsnmpfm/node.dart';
import 'dart:io' show Platform;  //at the top

void main() {
  final os = Platform.operatingSystem; //in your code
  print(os);
  WidgetsFlutterBinding.ensureInitialized();
  final nodes = Nodes();
  group('Nodes', () {
    test('nodes add', () {
      expect(
          nodes.add(Node(
            name: "node 1",
            ip: "192.168.1.1",
            community: "public",
            snmpMode: "v2c",
          )),
          true);
    });

    test('nodes update', () {
      expect(
          nodes.update(
              0,
              Node(
                  name: "node 1",
                  ip: "192.168.1.1",
                  community: "public",
                  snmpMode: "v2c")),
          true);
    });

    test('nodes delete', () {
      expect(nodes.delete(0), true);
    });
  });
}

です。

例外の問題は調べるのに時間がかかりそうですが、今朝は時間切れです。

明日に続く

開発のための諸経費(機材、Appleの開発者、サーバー運用)に利用します。 ソフトウェアのマニュアルをnoteの記事で提供しています。 サポートによりnoteの運営にも貢献できるのでよろしくお願います。