Dart VM tests with `dart:html` — yes, you can!

Daniel Varga
3 min readDec 15, 2017

--

Well, sort of. Let me clarify what I mean by yes, you can. By default, running VM tests doesn’t allow for dart:html import. If you try, you will see a message similar to this:

Unable to spawn isolate: The built-in library 'dart:html' is not available on the stand-alone VM.

You can still run such tests in a browser (Dart won’t leave you hanging) by simply passing -p somebrowser to pub. More info about supported platforms here. However, this has some drawbacks:

  • you must have some kind of browser to run them
  • they are always slower than VM tests
  • sometimes you just need a super-small subset of browser functionality to get going
  • sometimes dart:html features are completely unused, transitive dependency that should not have any effect or impact on the test results*

I build Angular Dart applications with complex business logic. A lot of the code is completely decoupled from the browser that can be easily unit-tested, however some have that annoying transitive import somewhere deep in the code. A way I found to deal with this is via optional imports. A side note: I still have concerns about this approach and will be interested to read community response to it.

* You will need a transformer or similar mechanics to go over source files and make sure that server compatible imports are used — everywhere.

The magic of optional imports

Or you might see them as “configuration specific imports”. A quick google search will reveal poor results to understand it. In short, the syntax looks like this:

import "something.dart" if (condition) "other.dart";

Very useful if your application/package targets multiple platforms such as browsers, NodeJS (eg. DartSass) or DartVM.

condition is evaluated to true by passing a -D flag to dart command.

dart -Dcondition=true my_app.dart

or by setting a special DART_VM_OPTIONS environment variable. This latter is particularly useful if you intend to run your app via pub or other build tools. (again, search for this in google site:dartlang.org "DART_VM_OPTIONS" )

A simple use-case

Consider the following piece of code and the test to it.

All it does: naively extracts textual content split by space from a piece of markup. One could go to great lengths to make this functionality VM compatible by parsing, sanitizing the input or could go the quicker route: use what we already got to do the same.

One problem: won’t run on VM.

Let’s alter it (patch syntax ahead)

-import 'dart:html';
+import 'dart:html' if (dart_vm) 'package:html/dom.dart';

With the modification of that one line — symbols that are normally in dart:html and is only available in the browser — are available on the VM as well. package:html offers a lot of the same (mostly compatible) functionality.

To run this test, the following one-liner can be used to set the appropriate VM flag and lunch it via pub.

DART_VM_OPTIONS=-Ddart_vm=true pub run test test/extract_test.dart

On windows you can do the same

set DART_VM_OPTIONS=-Ddart_vm=true
pub run test test\extract_test.dart

Test reliability matter

A personal note: there are things to consider when using this method. Developers should check if such package replacements can be made. Eg. implementations are compatible with each-other.

All in all, I hope you find the information useful. Thanks for the read!

--

--