Guinness2 is a port of the Jasmine library to Dart. It is based on the AngularDart implementation of Jasmine, and similar to Guinness but for dart:test instead of dart:unittest.
Backed by dart:test
instead of dart:unittest
. Run via pub run test
instead of a Karma setup.
Removed bits referring to 'runner' programatically - just use pub run test
. Removed deprecated
showStats option. Remove all context-keeping, as this is now handles by package:test directly.
You can find the Guinness installation instructions here.
import 'package:guinness2/guinness2.dart';
main() {
// your specs
}
If you are testing a client-side application, and you want to use html matchers, import the guinness_html
library.
import 'package:guinness2/guinness2_html.dart';
main() {
guinnessEnableHtmlMatchers();
// your specs
}
Guinness specs are comprised of describe
, it
, beforeEach
, and afterEach
blocks.
import 'package:guinness2/guinness2.dart';
main() {
describe("syntax", () {
beforeEach(() {
print("outer before");
});
afterEach(() {
print("outer after");
});
it("runs first", () {
print("first");
});
describe("nested describe", () {
beforeEach(() {
print("inner before");
});
afterEach(() {
print("inner after");
});
it("runs second", () {
print("second");
});
});
});
}
This will print:
outer before, first, outer after
outer before, inner before, second, inner after, outer after
- To exclude a
describe
, change it toxdescribe
. - To exclude an
it
, change it toxit
. - To make a
describe
exclusive, change it toddescribe
. - To make an
it
exclusive, change it toiit
. - Important: to run exclusive tests, add
--tags solo
to your command line invocation.
Guinness supports pending describe and it blocks (blocks without a callback).
describe("pending describe");
xdescribe("pending xdescribe");
it("pending it");
xit("pending xit");
Since Dart has built-in futures, the Guinness framework makes a good use out of them. If you return a future from
beforeEach
, afterEach
, or it
, the framework will wait for that future to be resolved.
For instance:
beforeEach(connectToTheDatabase);
where connectToTheDatabase
returns a future.
Similarly, you can write:
afterEach(releaseConnection);
You can also write async specs using the following technique:
it("should return an empty list when the database is empty", () {
return queryDatabase().then((results){
expect(results).toEqual([]);
});
});
If a returned future gets rejected, the test fails.
They way you write assertions in Guinness is by using the expect
function, as follows:
expect(2).toEqual(2);
These are a few examples:
expect(2).toEqual(2);
expect([1,2]).toContain(2);
expect(2).toBe(2);
expect(()=> throw "BOOM").toThrow();
expect(()=> throw "BOOM").toThrow("BOOM");
expect(()=> throw "Invalid Argument").toThrowWith(message: "Invalid");
expect(()=> throw new InvalidArgument()).toThrowWith(anInstanceOf: InvalidArgument);
expect(()=> throw new InvalidArgument()).toThrowWith(type: ArgumentException);
expect(false).toBeFalsy();
expect(null).toBeFalsy();
expect(true).toBeTruthy();
expect("any object").toBeTruthy();
expect("any object").toBeDefined();
expect(null).toBeNull();
expect("not null").toBeNotNull();
expect(2).not.toEqual(1);
expect([1,2]).not.toContain(3);
expect([1,2]).not.toBe([1,2]);
expect((){}).not.toThrow();
expect(null).not.toBeDefined();
expect(new DocumentFragment.html("<div>some html</div>"))
.toHaveHtml("<div>some html</div>");
expect(new DocumentFragment.html("<div>some text</div>"))
.toHaveText("some text");
expect(new DivElement()..classes.add('abc'))
.toHaveClass("abc");
expect(new DivElement()..attributes['attr'] = 'value')
.toHaveAttribute("attr");
expect(new DocumentFragment.html("<div>some html</div>"))
.not.toHaveHtml("<div>some other html</div>");
expect(new DocumentFragment.html("<div>some text</div>"))
.not.toHaveText("some other text");
expect(new DivElement()..classes.add('abc'))
.not.toHaveClass("def");
expect(new DivElement()..attributes['attr'] = 'value')
.not.toHaveAttribute("other-attr");
final select = new SelectElement();
select.children
..add(new OptionElement(value: "1"))
..add(new OptionElement(value: "2", selected: true))
..add(new OptionElement(value: "3"));
expect(select).toEqualSelect(["1", ["2"], "3"]);
You can also use unittest matchers, like this:
expect(myObject).to(beValid); // where beValid is a unittest matcher
To make migration from the unittest library to Guinness easier, expect
supports an optional second argument.
expect(myObject, beValid); // same as expect(myObject).to(beValid);
This keeps your unittest assertions working, so you can change them one by one.
Guinness supports Jasmine-like spy functions:
final s = guinness.createSpy("my spy");
expect(s).not.toHaveBeenCalled();
s(1);
expect(s).toHaveBeenCalled();
expect(s).toHaveBeenCalledOnce();
expect(s).toHaveBeenCalledWith(1);
expect(s).toHaveBeenCalledOnceWith(1);
expect(s).not.toHaveBeenCalledWith(2);
s(2);
expect((){
expect(s).toHaveBeenCalledOnce();
}).toThrow();
expect((){
expect(s).toHaveBeenCalledOnceWith(1);
}).toThrow();
In addition, Guinness support spy objects:
class SomeSpy extends SpyObject implements SomeInterface {}
...
final s = new SomeSpy();
s.invoke(1,2);
s.name;
s.name = 'some name';
expect(s.spy("invoke")).toHaveBeenCalled();
expect(s.spy("get:name")).toHaveBeenCalled();
expect(s.spy("set:name")).toHaveBeenCalled();
And:
final s = new SomeSpy();
s.spy("invoke").andCallFake((a,b) => a + b);
expect(s.invoke(1,2)).toEqual(3);
You can also use the mock
and dart_mocks
libraries with it.
Dart's package:test
supports most of the original Guinness test organization natively,
so we simply forward to the appropriate package:test
function.
The large exception is expectations, matchers, and spies, which are unchanged from original Guinness.