Isolates in Dart are a means for separating long running processes from the main thread of execution. I do not cover them in great detail in Dart for Hipsters. I do include a simple example. Since I have an example, I need to test that example.
The isolate example's calling context looks something like the following:
main() {
SendPort sender = spawnFunction(findDoom);
print('Certain doom awaits...');
var year = 2013;
sender.call(year).then((message) {
print("Doom in $year is on a $message.");
});
}I send to the long running findDoom() method, which I have spun up in its own spawnFunction() isolate. Testing of the calling context is a little tricky because of the asynchronous nature of the entire operation—who knows how long that findDoom() isolate might take to return? Also complicating things are those two print() methods. I have dealt with a single print statement in the past by overriding Dart's built-in print() method and testing the value printed. I could do something similar here, even with two print() statements instead of one.But then I get to thinking. What I really want to test here is that the isolate is running properly and returning a proper future value. I already know from last night how to test future values. The result of
sender.call(year) in my code example is a future, so I write a test that matches the expectation of that future:library isolate_test;
import 'package:unittest/unittest.dart';
import 'dart:isolate';
import '../main.dart' as Isolate;
run() {
group("[isolates]", (){
test('can send back replies', (){
SendPort sender = spawnFunction(Isolate.findDoom);
expect(sender.call(2013), completion("Thurs"));
});
});
}The test itself states the expectation of calling the long-running isolate with a value of 2013 is a future that will eventually complete with the value of Thursday (see the Doomsday Rule for the explanation of why). That is beautifully compact testing to express a fairly complex operation. To make that work, I import
dart:isolate (otherwise I would not have the spawnFunction() method). I also import my main source file with the Isolate prefix so that I don't have to worry about name clashes.After that, it just works:
➜ isolates git:(master) ✗ dart test/test.dart unittest-suite-wait-for-done PASS: [isolates] can send back replies All 1 tests passed.In keeping with my recent practices of not believing that testing something so complicated could be so easy, I intentionally break the expectation:
➜ isolates git:(master) ✗ dart test/test.dart
unittest-suite-wait-for-done
FAIL: [isolates] can send back replies
Expected: 'Fri'
but: was 'Thurs'.So I would seem to have a legitimate two-line test that verifies the result of a long running isolate process. I love it!Day #631
No comments:
Post a Comment