Dart 工程的单元测试

本文最后更新于 2021年4月4日 晚上

这篇文章是根据官方文档摘录的一些日常开发中常用内容, 方便日后查阅.

关于 Dart 中的单元测试

下面简略描述一下 Dart 中的单元测试应该如何进行, 更多内容详见官方文档.

  • 使用 test 函数写单元测试.

  • 使用 expect 函数进行断言.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    import "package:test/test.dart";

    void main() {
    test("String.split() splits the string on the delimiter", () {
    var string = "foo,bar,baz";
    expect(string.split(","), equals(["foo", "bar", "baz"]));
    });

    test("String.trim() removes surrounding whitespace", () {
    var string = " foo ";
    expect(string.trim(), equals("foo"));
    });
    }
  • 使用 group 包含多个单元测试:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    import "package:test/test.dart";

    void main() {
    group("String", () {
    test(".split() splits the string on the delimiter", () {
    var string = "foo,bar,baz";
    expect(string.split(","), equals(["foo", "bar", "baz"]));
    });

    test(".trim() removes surrounding whitespace", () {
    var string = " foo ";
    expect(string.trim(), equals("foo"));
    });
    });

    group("int", () {
    test(".remainder() returns the remainder of division", () {
    expect(11.remainder(3), equals(2));
    });

    test(".toRadixString() returns a hex string", () {
    expect(11.toRadixString(16), equals("b"));
    });
    });
    }
  • 使用 matcher 包中的若干方法可以进行复杂的断言验证:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import "package:test/test.dart";

    void main() {
    test(".split() splits the string on the delimiter", () {
    expect("foo,bar,baz", allOf([
    contains("foo"),
    isNot(startsWith("bar")),
    endsWith("baz")
    ]));
    });
    }
  • 使用 setUptearDown 来在每个单元测试执行前后插入需要执行的代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    import "package:test/test.dart";

    void main() {
    HttpServer server;
    Uri url;
    setUp(() async {
    server = await HttpServer.bind('localhost', 0);
    url = Uri.parse("http://${server.address.host}:${server.port}");
    });

    tearDown(() async {
    await server.close(force: true);
    server = null;
    url = null;
    });

    // ...
    }

    另外如果测试失败的话, tearDown 仍然会执行, 从而保证比如资源能正确释放等.

  • 指定在某些平台上进行单元测试, 则使用注解:

    1
    @TestOn("ios && android")
  • 普通异步测试, 这里有个好的地方是不用手动去指定等待时间这些杂鱼, 而是可以使用 async 和 await 来等待:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import "dart:async";

    import "package:test/test.dart";

    void main() {
    test("new Future.value() returns the value", () async {
    var value = await new Future.value(10);
    expect(value, equals(10));
    });
    }
  • 使用 completion() 的异步测试: 可以用这个 matcher 包中的方法来测试 Future:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    import "dart:async";

    import "package:test/test.dart";

    void main() {
    test("new Future.value() returns the value", () {
    expect(new Future.value(10), completion(equals(10)));
    });
    }
  • 使用 throwsA() 或类似的方法: 可以用它们来验证 Future 中抛出的特定异常:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import "dart:async";

    import "package:test/test.dart";

    void main() {
    test("new Future.error() throws the error", () {
    expect(new Future.error("oh no"), throwsA(equals("oh no")));
    expect(new Future.error(new StateError("bad state")), throwsStateError);
    });
    }

要执行单元测试, 使用如下命令:

1
2
3
4
5
6
7
# 运行某个文件中的单元测试
flutter test test/unit_test.dart
# 运行所有测试: 这个命令无法自动找到在 test 子文件夹中的单元测试, 故如果只执行单元测试, 可以使用下一个命令.
flutter test

# 更常用的是如下的命令: 执行 unit_test 文件夹下的所有单元测试.
flutter test --machine test/unit_tests/**

当然更简单的办法是直接使用 IDE 提供的测试执行按钮, 点一下就执行了.


Dart 工程的单元测试
https://blog.rayy.top/2019/03/03/2019-48-dart-unit-testing/
作者
貘鸣
发布于
2019年3月3日
许可协议