From d296e040bca1fe035120ec09e0341b7288ba5a9f Mon Sep 17 00:00:00 2001 From: Julie Ralph Date: Wed, 10 Feb 2016 15:43:51 -0800 Subject: [PATCH] refactor: vastly simplify guinness2 by removing all context. Almost everything that guinness does to keep track of suites and tests is now also handles by package test. So, instead of keeping tons of complex logic around, simply defer to package:test functions when possible. BREAKING CHANGE: `iit` and `ddescribe` NO LONGER modify which tests will run. Instead, they will mark those blocks with the tag "solo". To run only `iit` or `ddescribe` blocks, use the command line `pub run test --tags solo` (the same command you would use before, with the additional tags "solo"). See https://github.com/juliemr/guinness2/issues/1 --- README.md | 33 +--- example/example.dart | 2 +- lib/guinness2.dart | 7 +- lib/src/common/context.dart | 43 ----- lib/src/common/exclusive_visitor.dart | 26 --- lib/src/common/guinness_config.dart | 23 +-- lib/src/common/interfaces.dart | 8 - lib/src/common/model.dart | 123 ------------ lib/src/common/suite_info.dart | 92 --------- lib/src/common/syntax.dart | 42 +++-- lib/src/common/test_backend.dart | 83 -------- pubspec.yaml | 2 +- scripts/travis/run_tests.sh | 10 +- test/common/exclusive_visitor_test.dart | 65 ------- test/common/integration_test.dart | 143 -------------- test/common/model_test.dart | 177 ------------------ test/common/suite_info_test.dart | 110 ----------- test/common/syntax_test.dart | 150 --------------- test/common_test.dart | 22 --- test/guinness_test.dart | 20 -- test/html/test_backend_test.dart | 77 -------- test/test_utils.dart | 21 --- test_e2e/common/e2e_test.dart | 3 + .../{focused_it.dart => focused_it_test.dart} | 0 24 files changed, 43 insertions(+), 1239 deletions(-) delete mode 100644 lib/src/common/context.dart delete mode 100644 lib/src/common/exclusive_visitor.dart delete mode 100644 lib/src/common/model.dart delete mode 100644 lib/src/common/suite_info.dart delete mode 100644 test/common/exclusive_visitor_test.dart delete mode 100644 test/common/integration_test.dart delete mode 100644 test/common/model_test.dart delete mode 100644 test/common/suite_info_test.dart delete mode 100644 test/common/syntax_test.dart delete mode 100644 test/common_test.dart delete mode 100644 test/guinness_test.dart delete mode 100644 test/test_utils.dart rename test_e2e/focused/{focused_it.dart => focused_it_test.dart} (100%) diff --git a/README.md b/README.md index cdcf816..bff9756 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Guinness2 is a port of the Jasmine library to Dart. It is based on the AngularDa 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. +showStats option. Remove all context-keeping, as this is now handles by package:test directly. ## Installation @@ -41,7 +41,7 @@ Guinness specs are comprised of `describe`, `it`, `beforeEach`, and `afterEach` ```dart import 'package:guinness2/guinness2.dart'; -main(){ +main() { describe("syntax", () { beforeEach(() { print("outer before"); @@ -81,8 +81,7 @@ This will print: * To exclude an `it`, change it to `xit`. * To make a `describe` exclusive, change it to `ddescribe`. * To make an `it` exclusive, change it to `iit`. - -If there is an `iit` in your spec files, Guinness will run only `iit`s. In this case `ddescribe`s will be ignored. +* *Important:* to run exclusive tests, add `--tags solo` to your command line invocation. ### Pending Specs @@ -92,11 +91,9 @@ Guinness supports pending describe and it blocks (blocks without a callback). ```dart describe("pending describe"); xdescribe("pending xdescribe"); -ddescribe("pending ddescribe"); it("pending it"); xit("pending xit"); -iit("pending iit"); ``` ## Async @@ -264,29 +261,13 @@ expect(s.invoke(1,2)).toEqual(3); You can also use the `mock` and `dart_mocks` libraries with it. -## Status - -There are a few things that are still not supported (e.g., handling named parameters in expectations). ## Implementation Details ### Key Ideas -The main idea is to treat the Jasmine syntax as a domain specific language. Therefore, -the implementation clearly separates such things as: syntax, semantic model, and execution model. Let's quickly look - at the benefits this approach provides: - -#### The semantic model is separate from the syntax. - -The semantic model consists of It, Describe, Suite, BeforeEach, and AfterEach objects. You can create and analyse -them without using the context-dependent nested Jasmine syntax. - -#### The parsing of specs is separate from the execution of specs. - -The library builds a tree of the It, Describe, Suite, BeforeEach, and AfterEach objects first. And after that, -as a separate step, executes them. It enables all sorts of preprocessing (e.g., filtering, reordering). - -#### Pluggable backends. +Dart's `package:test` supports most of the original Guinness test organization natively, +so we simply forward to the appropriate `package:test` function. -Since the library is a DSL, there can be multiple backend libraries actually executing the specs. By default, -the library comes with the test backend. +The large exception is expectations, matchers, and spies, which are unchanged +from original Guinness. diff --git a/example/example.dart b/example/example.dart index a96b988..5669a00 100644 --- a/example/example.dart +++ b/example/example.dart @@ -8,7 +8,7 @@ import 'dart:html'; class TestClass {} main() { - GuinnessEnableHtmlMatchers(); + guinnessEnableHtmlMatchers(); describe("guinness2", () { it("has various built-in matchers", () { diff --git a/lib/guinness2.dart b/lib/guinness2.dart index 91446d1..90a165c 100644 --- a/lib/guinness2.dart +++ b/lib/guinness2.dart @@ -8,16 +8,12 @@ import 'dart:math' as math; export 'package:test/test.dart' show TestOn; -part 'src/common/model.dart'; -part 'src/common/context.dart'; part 'src/common/syntax.dart'; part 'src/common/expect.dart'; part 'src/common/spy.dart'; part 'src/common/interfaces.dart'; part 'src/common/guinness_config.dart'; part 'src/common/test_backend.dart'; -part 'src/common/exclusive_visitor.dart'; -part 'src/common/suite_info.dart'; class _Undefined { const _Undefined(); @@ -25,5 +21,4 @@ class _Undefined { const _u = const _Undefined(); final Guinness guinness = new Guinness( - matchers: new TestMatchers(), - initSpecs: testInitSpecs); + matchers: new TestMatchers()); diff --git a/lib/src/common/context.dart b/lib/src/common/context.dart deleted file mode 100644 index 70bc7ac..0000000 --- a/lib/src/common/context.dart +++ /dev/null @@ -1,43 +0,0 @@ -part of guinness2; - -class Context { - final List describes = []; - - Describe get currentDescribe => describes.last; - Describe get suite => describes.first; - - Context() { - describes.add(new Suite(this)); - } - - void withDescribe(Describe describe, Function definition) { - describes.add(describe); - try { - definition(); - } finally { - describes.removeLast(); - } - } - - void addBeforeEach(Function fn, {int priority}) { - final beforeEach = new BeforeEach(fn, priority: priority); - currentDescribe.addBeforeEach(beforeEach); - } - - void addAfterEach(Function fn, {int priority}) { - final afterEach = new AfterEach(fn, priority: priority); - currentDescribe.addAfterEach(afterEach); - } - - void addIt(String name, Function fn, {bool excluded, bool exclusive}) { - final it = new It(name, currentDescribe, fn, - excluded: excluded, exclusive: exclusive); - currentDescribe.add(it); - } - - void addDescribe(String name, Function fn, {bool excluded, bool exclusive}) { - final describe = new Describe(name, currentDescribe, this, fn, - excluded: excluded, exclusive: exclusive); - currentDescribe.add(describe); - } -} diff --git a/lib/src/common/exclusive_visitor.dart b/lib/src/common/exclusive_visitor.dart deleted file mode 100644 index b7421db..0000000 --- a/lib/src/common/exclusive_visitor.dart +++ /dev/null @@ -1,26 +0,0 @@ -part of guinness2; - -class ExclusiveVisitor implements SpecVisitor { - bool containsExclusiveIt = false; - bool containsExclusiveDescribe = false; - - void visitSuite(Suite suite) { - _visitChildren(suite.children); - } - - void visitDescribe(Describe describe) { - if (describe.excluded) return; - if (describe.exclusive) containsExclusiveDescribe = true; - - _visitChildren(describe.children); - } - - void visitIt(It it) { - if (it.excluded) return; - if (it.exclusive) containsExclusiveIt = true; - } - - _visitChildren(children) { - children.forEach((c) => c.visit(this)); - } -} diff --git a/lib/src/common/guinness_config.dart b/lib/src/common/guinness_config.dart index 9ddb836..2440670 100644 --- a/lib/src/common/guinness_config.dart +++ b/lib/src/common/guinness_config.dart @@ -1,14 +1,9 @@ part of guinness2; class Guinness { - Context _context = new Context(); dynamic matchers; - SpecRunner _initSpecs; - bool autoInit = true; - Guinness({this.matchers, SpecRunner initSpecs}) - : _initSpecs = initSpecs { - _scheduleAutoInit(); + Guinness({this.matchers}) { } SpyFunction createSpy([String name]) => new SpyFunction(name); @@ -16,20 +11,4 @@ class Guinness { SpyFunction spyOn(obj, String name) { throw "Not implemented"; } - - void initSpecs() { - _initSpecs(_context.suite); - } - - void resetContext([Context context]) { - _context = context == null ? new Context() : context; - } - - SuiteInfo suiteInfo() => _suiteInfo(_context.suite); - - void _scheduleAutoInit() { - async.scheduleMicrotask(() { - if (autoInit) initSpecs(); - }); - } } diff --git a/lib/src/common/interfaces.dart b/lib/src/common/interfaces.dart index d37ceaa..b8091b2 100644 --- a/lib/src/common/interfaces.dart +++ b/lib/src/common/interfaces.dart @@ -1,13 +1,5 @@ part of guinness2; -typedef void SpecRunner(Suite suite); - -abstract class SpecVisitor { - void visitSuite(Suite suite); - void visitDescribe(Describe describe); - void visitIt(It it); -} - abstract class Matchers { dynamic get config; diff --git a/lib/src/common/model.dart b/lib/src/common/model.dart deleted file mode 100644 index 5f2fb0c..0000000 --- a/lib/src/common/model.dart +++ /dev/null @@ -1,123 +0,0 @@ -part of guinness2; - -class BeforeEach { - final Function fn; - final int priority; - - BeforeEach(this.fn, {this.priority}); - - call() => fn(); -} - -class AfterEach { - final Function fn; - final int priority; - - AfterEach(this.fn, {this.priority}); - - call() => fn(); -} - -abstract class Spec { - final String name; - final Describe parent; - final bool excluded; - final bool exclusive; - final bool pending; - - Spec(this.name, this.parent, {this.excluded, this.exclusive, this.pending}); -} - -class It extends Spec { - final Function fn; - - It(String name, Describe parent, Function fn, {bool excluded, bool exclusive}) - : super(name, parent, - excluded: excluded, exclusive: exclusive, pending: fn == null), - this.fn = fn; - - String get name => pending ? 'PENDING: ${super.name}' : super.name; - - Function get withSetupAndTeardown { - if (pending) { - return () => new async.Future.value(true); - } else { - return () => _runAllBeforeEach().then(_runItWithAfterEach); - } - } - - Iterable get beforeEachFns { - final fns = []; - var c = parent; - while (c != null) { - fns.insertAll(0, c.beforeEachFns); - c = c.parent; - } - fns.sort((a, b) => Comparable.compare(b.priority, a.priority)); - return fns; - } - - Iterable get afterEachFns { - final fns = []; - var c = parent; - while (c != null) { - fns.addAll(c.afterEachFns); - c = c.parent; - } - fns.sort((a, b) => Comparable.compare(b.priority, a.priority)); - return fns; - } - - void visit(SpecVisitor visitor) => visitor.visitIt(this); - - _runItWithAfterEach(_) { - final success = (_) => _runAllAfterEach(); - final failure = (errorThrownByIt, stackTrace) => _runAllAfterEach() - .whenComplete( - () => new async.Future.error(errorThrownByIt, stackTrace)); - return _runIt().then(success, onError: failure); - } - - _runIt() => new async.Future.sync(fn); - _runAllBeforeEach() => _runAll(beforeEachFns); - _runAllAfterEach() => _runAll(afterEachFns); - _runAll(List fns) => async.Future.forEach(fns, (fn) => fn()); -} - -class Describe extends Spec { - final Context context; - final List beforeEachFns = []; - final List afterEachFns = []; - final List children = []; - - Describe(String name, Describe parent, this.context, Function definition, - {bool excluded, bool exclusive}) - : super(name, parent, - excluded: excluded, - exclusive: exclusive, - pending: definition == null) { - if (definition != null) context.withDescribe(this, definition); - } - - void addBeforeEach(BeforeEach beforeEach) { - beforeEachFns.add(beforeEach); - } - - void addAfterEach(AfterEach afterEach) { - afterEachFns.add(afterEach); - } - - void add(child) { - children.add(child); - } - - String get name => exclusive ? 'DDESCRIBE: ${super.name}' : super.name; - - void visit(SpecVisitor visitor) => visitor.visitDescribe(this); -} - -class Suite extends Describe { - Suite(Context context) : super(null, null, context, () {}); - - void visit(SpecVisitor visitor) => visitor.visitSuite(this); -} diff --git a/lib/src/common/suite_info.dart b/lib/src/common/suite_info.dart deleted file mode 100644 index ca29309..0000000 --- a/lib/src/common/suite_info.dart +++ /dev/null @@ -1,92 +0,0 @@ -part of guinness2; - -_suiteInfo(Suite suite) { - final visitor = new _SuiteInfoVisitor(); - visitor.visitSuite(suite); - return visitor.info; -} - -class SuiteInfo { - final List exclusiveDescribes = []; - final List excludedDescribes = []; - final List pendingDescribes = []; - - final List exclusiveIts = []; - final List excludedIts = []; - final List activeIts = []; - final List pendingIts = []; - - int numberOfIts = 0; - int numberOfDescribes = 0; - - int get numberOfActiveIts => activeIts.length; - bool get hasActiveIts => activeIts.isNotEmpty; - int get activeItsPercent => - numberOfIts > 0 ? (activeIts.length / numberOfIts * 100).toInt() : 0; -} - -class _SuiteInfoVisitor implements SpecVisitor { - final SuiteInfo info = new SuiteInfo(); - - bool containsExclusiveIt; - bool containsExclusiveDescribe; - - void visitSuite(Suite suite) { - final v = new ExclusiveVisitor(); - v.visitSuite(suite); - containsExclusiveIt = v.containsExclusiveIt; - containsExclusiveDescribe = v.containsExclusiveDescribe; - - _visitChildren(suite.children); - } - - void visitDescribe(Describe describe) { - if (describe.excluded) info.excludedDescribes.add(describe); - if (describe.exclusive) info.exclusiveDescribes.add(describe); - if (describe.pending) info.pendingDescribes.add(describe); - - info.numberOfDescribes += 1; - - _visitChildren(describe.children); - } - - void visitIt(It it) { - if (it.excluded) info.excludedIts.add(it); - if (it.exclusive) info.exclusiveIts.add(it); - if (it.pending) info.pendingIts.add(it); - - info.numberOfIts += 1; - - if (_isActive(it)) info.activeIts.add(it); - } - - bool _isActive(it) { - if (it.pending) { - return false; - } else if (containsExclusiveIt) { - return it.exclusive; - } else if (containsExclusiveDescribe) { - return _exclusiveParent(it.parent); - } else { - return _activeParent(it.parent); - } - } - - void _visitChildren(children) { - children.forEach((c) => c.visit(this)); - } - - bool _exclusiveParent(spec) { - if (spec == null) return false; - if (spec.excluded == true) return false; - if (spec.exclusive == true) return true; - return _exclusiveParent(spec.parent); - } - - bool _activeParent(spec) { - if (spec == null) return true; - if (spec.excluded == true) return false; - if (spec.exclusive == true) return true; - return _activeParent(spec.parent); - } -} diff --git a/lib/src/common/syntax.dart b/lib/src/common/syntax.dart index a8cdd58..bc18287 100644 --- a/lib/src/common/syntax.dart +++ b/lib/src/common/syntax.dart @@ -1,28 +1,34 @@ part of guinness2; -void beforeEach(Function fn, {int priority: 0}) => - guinness._context.addBeforeEach(fn, priority: priority); - -void afterEach(Function fn, {int priority: 0}) => - guinness._context.addAfterEach(fn, priority: priority); - -void it(name, [Function fn]) => guinness._context.addIt(name.toString(), fn, - excluded: false, exclusive: false); +void beforeEach(Function fn) => + dartTest.setUp(fn); + +void afterEach(Function fn) => + dartTest.tearDown(fn); + +void it(name, [Function fn]) { + if (fn != null) { + dartTest.test(name, fn); + } else { + dartTest.test(name, () {}, skip: 'skipping emtpy it'); + } +} -void xit(name, [Function fn]) => guinness._context.addIt(name.toString(), fn, - excluded: true, exclusive: false); +void xit(name, [Function fn]) => dartTest.test(name, fn, skip: 'skipping xit'); -void iit(name, [Function fn]) => guinness._context.addIt(name.toString(), fn, - excluded: false, exclusive: true); +void iit(name, [Function fn]) => dartTest.test(name, fn, tags: 'solo'); -void describe(name, [Function fn]) => guinness._context.addDescribe( - name.toString(), fn, excluded: false, exclusive: false); +void describe(name, [Function fn]) { + if (fn != null) { + dartTest.group(name, fn); + } else { + dartTest.group(name, () {}, skip: 'skipping empty describe'); + } +} -void xdescribe(name, [Function fn]) => guinness._context.addDescribe( - name.toString(), fn, excluded: true, exclusive: false); +void xdescribe(name, [Function fn]) => dartTest.group(name, fn, skip: 'skipping xdescribe'); -void ddescribe(name, [Function fn]) => guinness._context.addDescribe( - name.toString(), fn, excluded: false, exclusive: true); +void ddescribe(name, [Function fn]) => dartTest.group(name, fn, tags: 'solo'); Expect expect(actual, [matcher]) { final expect = new Expect(actual); diff --git a/lib/src/common/test_backend.dart b/lib/src/common/test_backend.dart index b93160a..9ad3a44 100644 --- a/lib/src/common/test_backend.dart +++ b/lib/src/common/test_backend.dart @@ -1,81 +1,5 @@ part of guinness2; -class TestAdapter { - const TestAdapter(); - void group(String name, Function fn) => dartTest.group(name, fn); - void test(String name, Function fn) => dartTest.test(name, fn); -} - -class TestVisitor implements SpecVisitor { - bool containsExclusiveIt = false; - bool containsExclusiveDescribe = false; - Set initializedSpecs; - dynamic dartTest; - - TestVisitor(this.initializedSpecs, {this.dartTest: const TestAdapter()}); - - void visitSuite(Suite suite) { - final v = new ExclusiveVisitor(); - v.visitSuite(suite); - // v now has containsExclusiveIt and containsExclusiveDescibe properties for the whole suite - - containsExclusiveIt = v.containsExclusiveIt; - - // If there is an exclusive it, ignore exclusive describes. - containsExclusiveDescribe = !containsExclusiveIt && v.containsExclusiveDescribe; - - if (containsExclusiveDescribe) { - _visitChildDescribes(suite.children); - } else { - _visitChildren(suite.children); - } - } - - void visitDescribe(Describe describe) { - _once(describe, () { - if (describe.excluded) return; - - // If there exists an exclusive describe, and this isn't it, only look - // at children that are instances of Describe. - if (containsExclusiveDescribe && !describe.exclusive) { - _visitChildDescribes(describe.children); - } - - dartTest.group(describe.name, () { - _visitChildren(describe.children); - }); - }); - } - - void visitIt(It it) { - _once(it, () { - if (it.excluded) return; - - if (containsExclusiveIt && !it.exclusive) return; - - dartTest.test(it.name, it.withSetupAndTeardown); - }); - } - - _visitChildren(children) { - children.forEach((c) => c.visit(this)); - } - - _visitChildDescribes(children) { - children.forEach((c) { - if (c is Describe) { - c.visit(this); - } - }); - } - - _once(spec, Function func) { - if (initializedSpecs.contains(spec)) return; - func(); - initializedSpecs.add(spec); - } -} - class TestMatchers implements Matchers { get config => {}; @@ -349,11 +273,4 @@ class IsInstanceOf extends dartTest.Matcher { description.add('an instance of $_type'); } -Set _initializedSpecs = new Set(); - -void testInitSpecs(Suite suite) { - var r = new TestVisitor(_initializedSpecs); - suite.visit(r); -} - bool get _isDart2js => identical(1, 1.0); diff --git a/pubspec.yaml b/pubspec.yaml index 06a0908..e11ffd4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -5,7 +5,7 @@ homepage: https://github.com/juliemr/guinness2 description: A port of the Jasmine testing framework. dependencies: collection: ">=1.4.0 <2.0.0" - test: "^0.12.9" + test: "^0.12.10" dev_dependencies: mockito: "0.11.0" environment: diff --git a/scripts/travis/run_tests.sh b/scripts/travis/run_tests.sh index 09776fa..3e1140e 100755 --- a/scripts/travis/run_tests.sh +++ b/scripts/travis/run_tests.sh @@ -56,7 +56,7 @@ function testAndVerifyOutput { set +e -testAndVerifyOutput "pub run test test_e2e/common -r expanded --no-color" "+7: All tests passed" +testAndVerifyOutput "pub run test test_e2e/common -r expanded --no-color" "+7 ~3: All tests passed" testAndVerifyOutput "pub run test test_e2e/html -r expanded --no-color" "No tests ran" @@ -64,10 +64,10 @@ testAndVerifyOutput "pub run test test_e2e/html -p dartium -r expanded --no-colo # TODO - uncomment when focused tests are working. -# testAndVerifyOutput "pub run test test_e2e/focused -r expanded --no-color" "+1 All tests passed" +testAndVerifyOutput "pub run test test_e2e/focused --tags solo -r expanded --no-color" "+1: All tests passed" -# testAndVerifyOutput "pub run test test_e2e/focused_describe -r expanded --no-color" "+2 All tests passed" +testAndVerifyOutput "pub run test test_e2e/focused_describe --tags solo -r expanded --no-color" "+2: All tests passed" -testAndVerifyOutput "pub run test -p dartium -r expanded --no-color" "+312: All tests passed" +testAndVerifyOutput "pub run test -p dartium -r expanded --no-color" "+75: All tests passed" -testAndVerifyOutput "pub run test example/example.dart -p dartium -r expanded --no-color" "+6: All tests passed" +testAndVerifyOutput "pub run test example/example.dart -p dartium -r expanded --no-color" "+5 ~4: All tests passed" diff --git a/test/common/exclusive_visitor_test.dart b/test/common/exclusive_visitor_test.dart deleted file mode 100644 index 9500e64..0000000 --- a/test/common/exclusive_visitor_test.dart +++ /dev/null @@ -1,65 +0,0 @@ -library guinness2.test.exclusive_visitor_test; - -import 'package:guinness2/guinness2.dart' as guinness2; -import 'package:test/test.dart'; - -import '../test_utils.dart'; - -bool _containsExclusiveIt(suite) { - final v = new guinness2.ExclusiveVisitor(); - v.visitSuite(suite); - return v.containsExclusiveIt; -} - -bool _containsExclusiveDescribe(suite) { - final v = new guinness2.ExclusiveVisitor(); - v.visitSuite(suite); - return v.containsExclusiveDescribe; -} - -void main() { - group("[containsExlclusiveIt]", () { - test("return true when a suite has an iit", () { - final suite = createSuite() - ..add(createDescribe()..add(createIt(exclusive: true))); - - expect(_containsExclusiveIt(suite), isTrue); - }); - - test("ignores iit inside xdescribe", () { - final suite = createSuite() - ..add(createDescribe(excluded: true)..add(createIt(exclusive: true))); - - expect(_containsExclusiveIt(suite), isFalse); - }); - - test("returns false otherwise", () { - final suite = createSuite() - ..add(createDescribe()..add(createIt(exclusive: false))); - - expect(_containsExclusiveIt(suite), isFalse); - }); - }); - - group("[containsExlclusiveDescribe]", () { - test("return true when a suite has an ddescribe", () { - final suite = createSuite()..add(createDescribe(exclusive: true)); - - expect(_containsExclusiveDescribe(suite), isTrue); - }); - - test("ignores ddescribe inside xdescribe", () { - final suite = createSuite() - ..add(createDescribe(excluded: true) - ..add(createDescribe(exclusive: true))); - - expect(_containsExclusiveDescribe(suite), isFalse); - }); - - test("returns false otherwise", () { - final suite = createSuite()..add(createDescribe()); - - expect(_containsExclusiveDescribe(suite), isFalse); - }); - }); -} diff --git a/test/common/integration_test.dart b/test/common/integration_test.dart deleted file mode 100644 index d5836a6..0000000 --- a/test/common/integration_test.dart +++ /dev/null @@ -1,143 +0,0 @@ -library guinness2.test.integration_test; - -import 'dart:async'; - -import 'package:guinness2/guinness2.dart' as guinness2; -import 'package:test/test.dart'; - -class DummyVisitor implements guinness2.SpecVisitor { - List allFutures = []; - - void visitSuite(guinness2.Suite suite) { - suite.children.forEach((c) => c.visit(this)); - } - - void visitDescribe(guinness2.Describe describe) { - describe.children.forEach((c) => c.visit(this)); - } - - void visitIt(guinness2.It it) { - allFutures.add(it.withSetupAndTeardown()); - } - - waitForAll() => Future.wait(allFutures); -} - -main() { - var context; - - void verify(Function fn) { - final visitor = new DummyVisitor(); - context.suite.visit(visitor); - visitor - .waitForAll() - .then(expectAsync((_) => fn())) - .catchError((e) => print(e)); - } - - setUp(() { - context = new guinness2.Context(); - guinness2.guinness.resetContext(context); - }); - - test("runs specs once", () { - var log = []; - - guinness2.describe("outer describe", () { - guinness2.it("outer it", () { - log.add("outer it"); - }); - - guinness2.describe("inner describe", () { - guinness2.it("inner it", () { - log.add("inner it"); - }); - }); - }); - - verify(() { - expect(log, equals(["outer it", "inner it"])); - }); - }); - - test("runs beforeEach and afterEach blocks", () { - var log = []; - - guinness2.describe("outer describe", () { - guinness2.beforeEach(() { - log.add("outer beforeEach"); - }); - - guinness2.afterEach(() { - log.add("outer afterEach"); - }); - - guinness2.describe("inner describe", () { - guinness2.beforeEach(() { - log.add("inner beforeEach"); - }); - - guinness2.afterEach(() { - log.add("inner afterEach"); - }); - - guinness2.it("inner it", () { - log.add("inner it"); - }); - }); - }); - - verify(() { - expect(log, equals([ - "outer beforeEach", - "inner beforeEach", - "inner it", - "inner afterEach", - "outer afterEach" - ])); - }); - }); - - group("when beforeEach, afterEach, and it return futures", () { - test("waits for them to be completed", () { - var log = []; - - futurePrinting(message) => new Future.microtask(() { - log.add(message); - }); - - guinness2.describe("outer describe", () { - guinness2.beforeEach(() => futurePrinting("outer beforeEach")); - guinness2.afterEach(() => futurePrinting("outer afterEach")); - - guinness2.describe("inner describe", () { - guinness2.beforeEach(() => futurePrinting("inner beforeEach")); - guinness2.afterEach(() => futurePrinting("inner afterEach")); - - guinness2.it("inner it", () => futurePrinting("inner it")); - }); - }); - - verify(() { - expect(log, equals([ - "outer beforeEach", - "inner beforeEach", - "inner it", - "inner afterEach", - "outer afterEach" - ])); - }); - }); - }); - - test("pending describes and its", () { - guinness2.describe("pending describe"); - guinness2.xdescribe("pending excluded describe"); - guinness2.ddescribe("pending exclusive describe"); - - guinness2.it("pending it"); - guinness2.xit("pending exlcluded it"); - guinness2.iit("pending exclusive it"); - verify(() {}); - }); -} diff --git a/test/common/model_test.dart b/test/common/model_test.dart deleted file mode 100644 index 329c938..0000000 --- a/test/common/model_test.dart +++ /dev/null @@ -1,177 +0,0 @@ -library guinness2.test.model_test; - -import 'dart:async'; - -import 'package:guinness2/guinness2.dart' as guinness2; -import 'package:test/test.dart'; - -import '../test_utils.dart'; - -void main() { - group("[It]", () { - test("returns all before each functions", () { - final outerBeforeEach = new guinness2.BeforeEach(noop, priority: 0); - final outer = createDescribe()..addBeforeEach(outerBeforeEach); - - final innerBeforeEach = new guinness2.BeforeEach(noop, priority: 0); - final inner = createDescribe(parent: outer) - ..addBeforeEach(innerBeforeEach); - - final it = createIt(parent: inner); - - expect(it.beforeEachFns, equals([outerBeforeEach, innerBeforeEach])); - }); - - test("returns all after each functions", () { - final outerAfterEach = new guinness2.AfterEach(noop, priority: 0); - final outer = createDescribe()..addAfterEach(outerAfterEach); - - final innerAfterEach = new guinness2.AfterEach(noop, priority: 0); - final inner = createDescribe(parent: outer)..addAfterEach(innerAfterEach); - - final it = createIt(parent: inner); - - expect(it.afterEachFns, equals([innerAfterEach, outerAfterEach])); - }); - - test("sorts all beforeEach fns by priority", () { - final beforeEach1 = new guinness2.BeforeEach(noop, priority: 0); - final beforeEach2 = new guinness2.BeforeEach(noop, priority: 1); - - final describe = createDescribe() - ..addBeforeEach(beforeEach1) - ..addBeforeEach(beforeEach2); - - final it = createIt(parent: describe); - - expect(it.beforeEachFns, equals([beforeEach2, beforeEach1])); - }); - - test("sorts all afterEach fns by priority", () { - final afterEach1 = new guinness2.AfterEach(noop, priority: 0); - final afterEach2 = new guinness2.AfterEach(noop, priority: 1); - - final describe = createDescribe() - ..addAfterEach(afterEach1) - ..addAfterEach(afterEach2); - - final it = createIt(parent: describe); - - expect(it.afterEachFns, equals([afterEach2, afterEach1])); - }); - - test("runs async beforeEach callbacks in order", () { - final log = []; - - createBeforeEach(delay, message) { - var func = () => new Future.delayed( - new Duration(milliseconds: delay), () => log.add(message)); - return new guinness2.BeforeEach(func, priority: 1); - } - - final beforeEach1 = createBeforeEach(2, "one"); - final beforeEach2 = createBeforeEach(1, "two"); - - final describe = createDescribe() - ..addBeforeEach(beforeEach1) - ..addBeforeEach(beforeEach2); - - final it = createIt(parent: describe); - - it.withSetupAndTeardown().then(expectAsync((_) { - expect(log, equals(["one", "two"])); - })); - }); - - test("runs async afterEach callbacks in order", () { - final log = []; - - createAfterEach(delay, message) { - var func = () => new Future.delayed( - new Duration(milliseconds: delay), () => log.add(message)); - return new guinness2.AfterEach(func, priority: 1); - } - - final afterEach1 = createAfterEach(2, "one"); - final afterEach2 = createAfterEach(1, "two"); - - final describe = createDescribe() - ..addAfterEach(afterEach1) - ..addAfterEach(afterEach2); - - final it = createIt(parent: describe); - - it.withSetupAndTeardown().then(expectAsync((_) { - expect(log, equals(["one", "two"])); - })); - }); - - test("does not run any callbacks when pending", () { - final log = []; - - final be = new guinness2.BeforeEach(() => log.add("before"), priority: 0); - final ae = new guinness2.AfterEach(() => log.add("after"), priority: 0); - - final describe = createDescribe() - ..addBeforeEach(be) - ..addAfterEach(ae); - - final it = createIt(parent: describe, func: null); - - it.withSetupAndTeardown().then(expectAsync((_) { - expect(log, isEmpty); - })); - }); - - group("[name]", () { - test("indicates that the spec is pending", () { - final it = createIt(name: "name", func: null); - - expect(it.name, equals("PENDING: name")); - }); - }); - - group("[error handling]", () { - test("does not run afterEach callbacks if beforeEach callbacks errored", - () { - final be = new guinness2.BeforeEach(() => throw "BOOM", priority: 1); - - var run = false; - final ae = new guinness2.AfterEach(() => run = true, priority: 1); - - final describe = createDescribe() - ..addBeforeEach(be) - ..addAfterEach(ae); - - final it = createIt(parent: describe); - - it.withSetupAndTeardown().catchError(expectAsync((_) { - expect(run, isFalse); - })); - }); - - test("returns the original error when both it and afterEach throw", () { - final ae = new guinness2.AfterEach(() => throw "after", priority: 1); - final describe = createDescribe()..addAfterEach(ae); - - final it = new guinness2.It("it", describe, () => throw "it"); - - it.withSetupAndTeardown().catchError(expectAsync((err) { - expect(err, equals("it")); - })); - }); - - test("return the error thrown by `afterEach` if `it` returns normally", - () { - final ae = new guinness2.AfterEach(() => throw "after", priority: 1); - final describe = createDescribe()..addAfterEach(ae); - - final it = new guinness2.It("it", describe, noop); - - it.withSetupAndTeardown().catchError(expectAsync((err) { - expect(err, equals("after")); - })); - }); - }); - }); -} diff --git a/test/common/suite_info_test.dart b/test/common/suite_info_test.dart deleted file mode 100644 index 0993078..0000000 --- a/test/common/suite_info_test.dart +++ /dev/null @@ -1,110 +0,0 @@ -library guinness2.test.suit_info_test; - -import 'package:guinness2/guinness2.dart' as guinness2; -import 'package:test/test.dart'; - -import '../test_utils.dart'; - -void main() { - setUp(() { - final context = new guinness2.Context(); - guinness2.guinness.resetContext(context); - }); - - test("describes", () { - guinness2.describe("outer", () { - guinness2.xdescribe("xdescribe", noop); - guinness2.ddescribe("ddescribe", noop); - guinness2.describe("inner describe", noop); - }); - guinness2.describe("pending describe"); - - final suiteInfo = guinness2.guinness.suiteInfo(); - expect(suiteInfo.numberOfDescribes, equals(5)); - expect(suiteInfo.exclusiveDescribes.length, equals(1)); - expect(suiteInfo.excludedDescribes.length, equals(1)); - expect(suiteInfo.pendingDescribes.length, equals(1)); - }); - - test("its", () { - guinness2.it("one", noop); - guinness2.xit("two", noop); - guinness2.iit("three", noop); - guinness2.it("pending it"); - - final suiteInfo = guinness2.guinness.suiteInfo(); - expect(suiteInfo.numberOfIts, equals(4)); - expect(suiteInfo.exclusiveIts.length, equals(1)); - expect(suiteInfo.excludedIts.length, equals(1)); - expect(suiteInfo.pendingIts.length, equals(1)); - }); - - group("[activeIts]", () { - test("ignores its in xdescribe", () { - guinness2.it("one", noop); - - guinness2.xdescribe("xdescribe", () { - guinness2.it("two", noop); - }); - - final suiteInfo = guinness2.guinness.suiteInfo(); - expect(suiteInfo.activeIts.length, equals(1)); - }); - - test("ignores pending its", () { - guinness2.it("one"); - - final suiteInfo = guinness2.guinness.suiteInfo(); - expect(suiteInfo.activeIts.length, equals(0)); - }); - - test("counts only its in ddescribes", () { - guinness2.it("one", noop); - - guinness2.ddescribe("ddescribe", () { - guinness2.it("two", noop); - }); - - final suiteInfo = guinness2.guinness.suiteInfo(); - expect(suiteInfo.activeIts.length, equals(1)); - }); - - test("counts only iits", () { - guinness2.it("one", noop); - - guinness2.describe("describe", () { - guinness2.iit("two", noop); - }); - - final suiteInfo = guinness2.guinness.suiteInfo(); - expect(suiteInfo.activeIts.length, equals(1)); - }); - - test("ignores iits in xdescribe", () { - guinness2.it("one", noop); - - guinness2.xdescribe("xdescribe", () { - guinness2.iit("two", noop); - guinness2.iit("three", noop); - }); - - final suiteInfo = guinness2.guinness.suiteInfo(); - expect(suiteInfo.activeIts.length, equals(1)); - }); - - group('[activeItsPercent]', () { - test("is the percent of active tests in the suite", () { - guinness2.it("one", noop); - guinness2.iit("one", noop); - - final suiteInfo = guinness2.guinness.suiteInfo(); - expect(suiteInfo.activeItsPercent, equals(50)); - }); - - test("is zero when not specs", () { - final suiteInfo = guinness2.guinness.suiteInfo(); - expect(suiteInfo.activeItsPercent, equals(0)); - }); - }); - }); -} diff --git a/test/common/syntax_test.dart b/test/common/syntax_test.dart deleted file mode 100644 index 54d16dd..0000000 --- a/test/common/syntax_test.dart +++ /dev/null @@ -1,150 +0,0 @@ -library guinness2.test.syntax_test; - -import 'package:guinness2/guinness2.dart' as guinness2; -import 'package:test/test.dart'; - -void main() { - var context; - - setUp(() { - context = new guinness2.Context(); - guinness2.guinness.resetContext(context); - }); - - group("[describe]", () { - test("adds a describe to the current describe block", () { - guinness2.describe("new describe", () {}); - - final actualDescribe = context.suite.children.first; - - expect(actualDescribe.name, equals("new describe")); - }); - }); - - group("[xdescribe]", () { - test( - "adds a describe to the current describe block with excluded set to true", - () { - guinness2.xdescribe("new xdescribe", () {}); - - final actualDescribe = context.suite.children.first; - - expect(actualDescribe.name, equals("new xdescribe")); - expect(actualDescribe.excluded, isTrue); - }); - }); - - group("[ddescribe]", () { - test( - "adds a describe to the current describe block with exclusive set to true", - () { - guinness2.ddescribe("new ddescribe", () {}); - - final actualDescribe = context.suite.children.first; - - expect(actualDescribe.name, equals("DDESCRIBE: new ddescribe")); - expect(actualDescribe.exclusive, isTrue); - }); - }); - - group("[it]", () { - test("adds an `it` to the current describe block", () { - guinness2.it("new it", () {}); - - final actualIt = context.suite.children.first; - - expect(actualIt.name, equals("new it")); - expect(actualIt.excluded, isFalse); - expect(actualIt.exclusive, isFalse); - }); - }); - - group("[xit]", () { - test("adds an `it` to the current describe block with excluded set to true", - () { - guinness2.xit("new xit", () {}); - - final actualIt = context.suite.children.first; - - expect(actualIt.name, equals("new xit")); - expect(actualIt.excluded, isTrue); - }); - }); - - group("[iit]", () { - test( - "adds an `it` to the current describe block with exclusive set to true", - () { - guinness2.iit("new iit", () {}); - - final actualIt = context.suite.children.first; - - expect(actualIt.name, equals("new iit")); - expect(actualIt.exclusive, isTrue); - }); - }); - - group("[beforeEach]", () { - test("adds a before each fn to the current describe block", () { - guinness2.beforeEach(() {}); - - expect(context.suite.beforeEachFns.length, equals(1)); - expect(context.suite.beforeEachFns[0].priority, equals(0)); - }); - - test("supports different priorities", () { - guinness2.beforeEach(() {}, priority: 2); - - expect(context.suite.beforeEachFns[0].priority, equals(2)); - }); - }); - - group("[afterEach]", () { - test("adds a after each fn to the current describe block", () { - guinness2.afterEach(() {}); - - expect(context.suite.afterEachFns.length, equals(1)); - expect(context.suite.afterEachFns[0].priority, equals(0)); - }); - - test("supports different priorities", () { - guinness2.afterEach(() {}, priority: 2); - - expect(context.suite.afterEachFns[0].priority, equals(2)); - }); - }); - - test("handles nested describes and its", () { - guinness2.describe("outer describe", () { - guinness2.it("outer it", () {}); - guinness2.describe("inner describe", () { - guinness2.it("inner it", () {}); - }); - }); - - expect(context.suite.children.length, equals(1)); - - final outerDescribe = context.suite.children[0]; - expect(outerDescribe.name, equals("outer describe")); - expect(outerDescribe.children[0].name, equals("outer it")); - expect(outerDescribe.children[1].name, equals("inner describe")); - - final innerDescribe = outerDescribe.children[1]; - expect(innerDescribe.children.length, equals(1)); - expect(innerDescribe.children[0].name, equals("inner it")); - }); - - group("[expect]", () { - test("creates an Expect object", () { - final e = guinness2.expect("actual"); - - expect(e.actual, equals("actual")); - }); - - test("executes the given matcher", () { - expect(() { - guinness2.expect(true, isFalse); - }, throws); - }); - }); -} diff --git a/test/common_test.dart b/test/common_test.dart deleted file mode 100644 index 366cbae..0000000 --- a/test/common_test.dart +++ /dev/null @@ -1,22 +0,0 @@ -library guinness2.test.common_tests; - -import 'package:guinness2/guinness2.dart'; -import 'package:test/test.dart'; - -import 'common/exclusive_visitor_test.dart' as exclusive_visitor; -import 'common/integration_test.dart' as integration; -import 'common/model_test.dart' as model; -import 'common/spy_test.dart' as spy; -import 'common/suite_info_test.dart' as suite_info; -import 'common/syntax_test.dart' as syntax; - -void main() { - guinness.autoInit = false; - - group("[ExclusiveVisitor]", exclusive_visitor.main); - group("[integration]", integration.main); - group('[model]', model.main); - spy.main(); - group('[suiteInfo]', suite_info.main); - group('[syntax]', syntax.main); -} diff --git a/test/guinness_test.dart b/test/guinness_test.dart deleted file mode 100644 index c66ebed..0000000 --- a/test/guinness_test.dart +++ /dev/null @@ -1,20 +0,0 @@ -@TestOn('browser') - - -library guinness2_test; - -import 'package:guinness2/guinness2_html.dart'; -import 'dart:html'; - -import 'common_test.dart' as common; -import 'html/html_utils_test.dart' as htmlUtilsTest; -import 'html/test_backend_test.dart' as test_backend; - -void main() { - GuinnessEnableHtmlMatchers(); - guinness.autoInit = false; - - common.main(); - htmlUtilsTest.main(); - test_backend.main(); -} diff --git a/test/html/test_backend_test.dart b/test/html/test_backend_test.dart index 059bb92..f59319c 100644 --- a/test/html/test_backend_test.dart +++ b/test/html/test_backend_test.dart @@ -8,8 +8,6 @@ import 'package:mockito/mockito.dart'; import 'package:guinness2/guinness2_html.dart' as guinness2; import 'package:test/test.dart'; -import '../test_utils.dart'; - assertTrue(Function fn) => expect(fn, returnsNormally); assertFalse(Function fn) => expect(fn, throws); @@ -31,81 +29,6 @@ class MockTest extends Mock { } void main() { - group("[TestVisitor]", () { - var visitor, dartTest; - - setUp(() { - dartTest = new MockTest(); - visitor = new guinness2.TestVisitor(new Set(), dartTest: dartTest); - }); - - tearDown(() { - verifyNoMoreInteractions(dartTest); - }); - - test('handles an empty suite', () { - visitor.visitSuite(createSuite()); - }); - - test('uses group for describe', () { - final suite = createSuite()..add(createDescribe()); - - visitor.visitSuite(suite); - verify(dartTest.group(any, any)); - }); - - test('skips excluded describes', () { - final suite = createSuite()..add(createDescribe(excluded: true)); - - visitor.visitSuite(suite); - }); - - test('uses test for it', () { - final suite = createSuite()..add(createIt()); - - visitor.visitSuite(suite); - verify(dartTest.test(any, any)); - }); - - test('only adds exclusive it', () { - final suite = createSuite()..add(createIt(exclusive: true)) - ..add(createIt()); - - visitor.visitSuite(suite); - verify(dartTest.test(any, any)).called(1); - }); - - test('skips excluded its', () { - final suite = createSuite()..add(createIt(excluded: true)); - - visitor.visitSuite(suite); - }); - - test('runs only exlusive its', () { - final suite = createSuite(); - var exclusiveDescribe = createDescribe(exclusive: true); - var exclusiveIt = createIt(exclusive: true); - var otherIt = createIt(parent: exclusiveDescribe); - suite..add(exclusiveDescribe)..add(exclusiveIt); - - visitor.visitSuite(suite); - verify(dartTest.group(any, any)); - verify(dartTest.test(any, any)); - }); - - test("initializes specs only once", () { - final suite = createSuite() - ..add(createIt()) - ..add(createDescribe()); - - visitor.visitSuite(suite); - - visitor.visitSuite(suite); - verify(dartTest.test(any, any)); - verify(dartTest.group(any, any)); - }); - }); - group("[TestMatchers]", () { final matchers = new guinness2.TestMatchersWithHtml(); diff --git a/test/test_utils.dart b/test/test_utils.dart deleted file mode 100644 index 1eb74fe..0000000 --- a/test/test_utils.dart +++ /dev/null @@ -1,21 +0,0 @@ -library guinness2.test_utils; - -import 'package:guinness2/guinness2.dart' as guinness2; - -final _context = new _DummyContext(); - -noop() {} - -createSuite() => new guinness2.Suite(_context); - -createDescribe({bool exclusive: false, bool excluded: false, parent, - Function func: noop, String name: ""}) => new guinness2.Describe( - name, parent, _context, func, exclusive: exclusive, excluded: excluded); - -createIt({bool exclusive: false, bool excluded: false, parent, - Function func: noop, String name: ""}) => new guinness2.It( - name, parent, func, exclusive: exclusive, excluded: excluded); - -class _DummyContext implements guinness2.Context { - withDescribe(guinness2.Describe describe, Function definition) {} -} diff --git a/test_e2e/common/e2e_test.dart b/test_e2e/common/e2e_test.dart index 6047e0f..3fdadcc 100644 --- a/test_e2e/common/e2e_test.dart +++ b/test_e2e/common/e2e_test.dart @@ -18,4 +18,7 @@ main() { xit('skipped spec should not run', () { expect(1).toEqual(2); }); + + it('test without function should count as skipped'); + describe('describe without function should count as skipped'); } diff --git a/test_e2e/focused/focused_it.dart b/test_e2e/focused/focused_it_test.dart similarity index 100% rename from test_e2e/focused/focused_it.dart rename to test_e2e/focused/focused_it_test.dart