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