tests.trial.executors.parallel 80/88(90%) line coverage

      
10
20
30
40
50
60
70
80
90
100
110
120
130
140
150
160
171
180
190
200
219
2218
239
240
250
260
271
282
291
300
310
320
330
340
350
360
370
380
390
400
410
420
430
440
450
460
470
480
490
500
511
520
531
541
551
561
570
581
591
600
612
622
630
642
652
662
672
680
690
700
710
720
731
740
751
761
771
781
790
801
811
820
832
842
850
862
872
882
892
900
910
920
930
940
951
960
971
980
99158628
1000
1010
1020
1031
1040
1051
1061
1071
1080
1091
1101
1110
1121
1130
1142
1150
1160
1170
1180
1190
1201
1210
1221
1231
1241
1251
1260
1271
1280
1292
1302
1310
1322
1330
1340
1350
1360
1370
1381
1390
1400
1410
1420
1431
1441
1451
1460
1471
1480
1491
1500
1512
1522
1530
1542
1550
1560
1570
1580
1590
1600
1610
1621
1631
1641
1650
1662
1670
1680
1690
1702
1710
1720
1730
1742
1750
1760
1770
1782
1790
1800
1810
1822
1830
1840
1850
1862
1870
1880
1890
1901
1910
1921
1931
1941
1950
1961
1971
1980
1991
2000
2012
2020
2032
2040
module tests.trial.executors.parallel; import trial.executor.parallel; import trial.runner; import core.thread; import std.datetime; import std.conv; import fluent.asserts; import trial.step; __gshared bool executed; void failMock() @system { assert(false); } void stepMock1() @system { Thread.sleep(100.msecs); auto a = Step("some step"); executed = true; } void stepMock2() @system { Thread.sleep(200.msecs); auto a = Step("some step"); executed = true; } void stepMock3() @system { Thread.sleep(120.msecs); auto a = Step("some step"); executed = true; for(int i=0; i<3; i++) { Thread.sleep(120.msecs); stepFunction(i); Thread.sleep(120.msecs); } } void stepFunction(int i) { Step("Step " ~ i.to!string); } @("A parallel executor should get the result of a success test") unittest { TestCase[] tests = [ TestCase("suite1", "test1", &stepMock1)]; auto old = LifeCycleListeners.instance; scope(exit) LifeCycleListeners.instance = old; LifeCycleListeners.instance = new LifeCycleListeners; LifeCycleListeners.instance.add(new ParallelExecutor); auto begin = Clock.currTime; auto result = tests.runTests; result.length.should.equal(1); result[0].name.should.equal("suite1"); result[0].tests.length.should.equal(1); result[0].tests.length.should.equal(1); result[0].tests[0].status.should.equal(TestResult.Status.success); (result[0].tests[0].throwable is null).should.equal(true); } @("A parallel executor should get the result of a failing test") unittest { TestCase[] tests = [ TestCase("suite1", "test1", &failMock)]; auto old = LifeCycleListeners.instance; scope(exit) LifeCycleListeners.instance = old; LifeCycleListeners.instance = new LifeCycleListeners; LifeCycleListeners.instance.add(new ParallelExecutor); auto begin = Clock.currTime; auto result = tests.runTests; result.length.should.equal(1); result[0].name.should.equal("suite1"); result[0].tests.length.should.equal(1); result[0].tests.length.should.equal(1); result[0].tests[0].status.should.equal(TestResult.Status.failure); (result[0].tests[0].throwable !is null).should.equal(true); } @("it should call update() many times") unittest { ulong updated = 0; class MockListener : ILifecycleListener { void begin(ulong) {} void update() { updated++; } void end(SuiteResult[]) {} } TestCase[] tests = [ TestCase("suite2", "test1", &stepMock1) ]; auto old = LifeCycleListeners.instance; scope(exit) LifeCycleListeners.instance = old; LifeCycleListeners.instance = new LifeCycleListeners; LifeCycleListeners.instance.add(new MockListener); LifeCycleListeners.instance.add(new ParallelExecutor); auto results = tests.runTests; updated.should.be.greaterThan(50); } @("it should run the tests in parallel") unittest { TestCase[] tests = [ TestCase("suite2", "test1", &stepMock1), TestCase("suite2", "test3", &stepMock1), TestCase("suite2", "test2", &stepMock1) ]; auto old = LifeCycleListeners.instance; scope(exit) LifeCycleListeners.instance = old; LifeCycleListeners.instance = new LifeCycleListeners; LifeCycleListeners.instance.add(new ParallelExecutor); auto results = tests.runTests; results.length.should.equal(1); results[0].tests.length.should.equal(3); (results[0].end - results[0].begin).should.be.between(90.msecs, 120.msecs); } @("it should be able to limit the parallel tests number") unittest { TestCase[] tests = [ TestCase("suite2", "test1", &stepMock1), TestCase("suite2", "test3", &stepMock1), TestCase("suite2", "test2", &stepMock1) ]; auto old = LifeCycleListeners.instance; scope(exit) LifeCycleListeners.instance = old; LifeCycleListeners.instance = new LifeCycleListeners; LifeCycleListeners.instance.add(new ParallelExecutor(2)); auto results = tests.runTests; results.length.should.equal(1); results[0].tests.length.should.equal(3); (results[0].end - results[0].begin).should.be.between(200.msecs, 250.msecs); } @("A parallel executor should call the events in the right order") unittest { import core.thread; executed = false; string[] steps; class MockListener : IStepLifecycleListener, ITestCaseLifecycleListener, ISuiteLifecycleListener { void begin(string suite, string test, ref StepResult step) { steps ~= [ suite ~ "." ~ test ~ ".stepBegin " ~ step.name ]; } void end(string suite, string test, ref StepResult step) { steps ~= [ suite ~ "." ~ test ~ ".stepEnd " ~ step.name ]; } void begin(string suite, ref TestResult test) { steps ~= [ suite ~ ".testBegin " ~ test.name ]; } void end(string suite, ref TestResult test) { steps ~= [ suite ~ ".testEnd " ~ test.name ]; } void begin(ref SuiteResult suite) { steps ~= [ "begin " ~ suite.name ]; } void end(ref SuiteResult suite) { steps ~= [ "end " ~ suite.name ]; } } TestCase[] tests = [ TestCase("suite1", "test1", &stepMock1), TestCase("suite2","test2", &stepMock2) ]; auto old = LifeCycleListeners.instance; scope(exit) LifeCycleListeners.instance = old; LifeCycleListeners.instance = new LifeCycleListeners; LifeCycleListeners.instance.add(new MockListener); LifeCycleListeners.instance.add(new ParallelExecutor); auto results = tests.runTests; executed.should.equal(true); steps.should.contain(["begin suite1", "suite1.testBegin test1", "begin suite2", "suite2.testBegin test2", "suite1.test1.stepBegin some step", "suite1.test1.stepEnd some step", "suite2.test2.stepBegin some step", "suite2.test2.stepEnd some step", "suite1.testEnd test1", "suite2.testEnd test2", "end suite2", "end suite1"]); }