我正在为自定义 Flutter 包编写一堆带有 HTTP 客户端的单元测试。
我注意到,当我使用
flutter test
运行测试时,前两个单元测试将大约在同一时间开始。
这不是我想要的。因为单元测试应该写入一些数据,并且在每个单元测试开始时数据都会被重置。这样每个测试都以相同的数据开始。
但是由于有两个测试同时运行,它们都访问同一个文件并损坏它或无法使用
FileSystemException: lock failed
访问它。
有没有办法强制测试一项一项地运行,而不是一次运行多个? 我尝试将它们放在单独的文件中,但这不起作用。
谢谢
默认情况下,
flutter test
命令会并发执行测试,但您可以在flutter测试命令中使用-j, --concurrency=<jobs>
指定并发度。
根据 Flutter 帮助文档:
-j, --concurrency=<jobs>
定义要运行的并发测试进程的数量。运行集成测试时这将被忽略。 (默认为“14”)
执行以下命令来一一运行所有测试
flutter test -j, --concurrency=1
执行以下命令以覆盖率一一运行所有测试,
flutter test --coverage -j, --concurrency=1
如果您有多个彼此相关的测试,请使用测试包提供的组功能将它们组合起来。
请检查https://flutter.dev/docs/cookbook/testing/unit/introduction#5-combine-multiple-tests-in-a-group
我遇到了类似的问题,我需要按顺序运行一堆测试。我使用 futures 将这个近似信号量的小东西组合在一起,这对我的用例有用,也许对其他人也有用
您创建一个“序列”,然后将测试包装在
runInSequence(...)
中,如下所示
void main() {
final seq = newTestSequence();
for (int i = 1; i <= 10; i++) {
test('test $i', () async {
await runInSequence(seq, () async {
print('starting test $i...');
// your test code goes here
final sleepMs = 1000 - i * 10;
await Future.delayed(Duration(milliseconds: sleepMs));
print('test $i done');
});
});
}
}
这是
newSequence
和 runInSequence
的代码
import 'dart:async';
import 'package:flutter/widgets.dart';
final Map<Key, Completer> _semaphores = {};
Key newTestSequence() {
final sequence = GlobalKey();
// create a new "semaphore" that will allow the first awaiter through
// immediately
_semaphores[sequence] = Completer();
_semaphores[sequence]!.complete();
return sequence;
}
Future<void> runInSequence(Key sequence, Future Function() test) async {
// block until resource is acquired
final c = await _claimSemaphore(sequence);
// execute test
await test();
// release resource
c.complete();
}
Future<Completer> _claimSemaphore(Key sequence) async {
if (!_semaphores.containsKey(sequence)) {
throw "unknown sequence $sequence; create one using `newTestSequence`";
}
final Completer c = _semaphores[sequence]!;
// block execution until the future is completed
await c.future;
// replace completer because futures can only be completed once
_semaphores[sequence] = Completer();
return _semaphores[sequence]!;
}