fluentasserts.core.basetype 186/194(95%) line coverage

      
10
20
30
40
50
60
70
80
90
100
110
120
130
140
15125
16125
17125
180
190
200
210
220
230
240
250
260
270
2862
290
3061
3161
3261
3361
340
3561
360
370
3864
390
4058
410
420
4361
440
450
460
470
480
4915
500
5114
5214
5314
5414
550
5614
5728
5828
590
6014
610
620
630
640
650
660
670
6814
690
700
710
720
730
7417
750
7616
7716
7816
7916
800
8116
820
8316
840
850
8616
870
880
890
900
9132
920
9316
940
950
960
970
980
9929
1000
10156
10256
1030
10428
10528
10628
10728
10828
10928
1100
11128
11228
11351
1140
11528
1160
1170
11856
1190
12028
12114
1220
12314
1241
1250
1260
12714
1282
1290
1300
1310
13228
1330
1340
1350
1360
1370
1389
1390
1408
1418
1428
1438
1440
1458
1460
1470
1480
1490
1500
1511
1525
1530
1540
1553
1562
1570
1580
1593
1602
1610
1620
1633
1642
1650
1660
1673
1682
1690
1700
1713
1722
1730
1740
1750
1760
1770
1782
1792
1802
1810
1820
1833
1842
1850
1860
1872
1882
1892
1900
1913
1922
1930
1940
1952
1962
1972
1980
1990
2000
2010
2022
2032
2042
2050
2060
2073
2082
2090
2100
2112
2122
2132
2140
2153
2162
2170
2180
2192
2202
2212
2220
2230
2240
2250
2262
2272
2282
2290
2302
2312
2320
2330
2343
2352
2360
2370
2380
2392
2402
2412
2420
2433
2442
2450
2460
2470
2482
2492
2502
2510
2520
2530
2540
2552
2562
2572
2580
2592
2602
2610
2620
2633
2642
2650
2660
2670
2682
2692
2702
2710
2723
2732
2740
2750
2760
2772
2780
2790
2800
2810
2822
2832
2842
2852
2862
2870
2882
2892
2902
2912
2920
2930
2943
2952
2960
2970
2980
2992
3002
3012
3020
3033
3042
3050
3060
3070
3082
3092
3102
3110
3123
3132
3140
3150
3160
3172
3182
3192
3200
3213
3222
3230
3240
3250
3262
3272
3282
3290
3300
3310
3320
3332
3342
3352
3360
3370
3383
3392
3400
3410
3422
3432
3442
3450
3463
3472
3480
3490
3502
3512
3522
3530
3540
3550
3560
3571
3581
3590
3600
3611
3622
3630
3640
3651
3660
3672
3682
3690
3701
3710
3720
3732
3740
3752
3761
3770
3782
3790
3801
3810
3820
3832
3840
3851
3862
3870
3880
3892
3900
3910
3920
3930
3940
3951
3962
3970
module fluentasserts.core.basetype; public import fluentasserts.core.base; import fluentasserts.core.results; import std.string; import std.conv; import std.algorithm; @trusted: struct ShouldBaseType(T) { private const T testData; this(U)(U value) { valueEvaluation = value.evaluation; testData = value.value; } mixin ShouldCommons; mixin ShouldThrowableCommons; alias above = this.greaterThan; alias below = this.lessThan; alias within = this.between; auto equal(const T someValue, const string file = __FILE__, const size_t line = __LINE__) { validateException; addMessage(" equal `"); addValue(someValue.to!string); addMessage("`"); beginCheck; auto isSame = testData == someValue; static if(is( T == bool )) { auto expected = expectedValue ? someValue.to!string : (!someValue).to!string; } else { auto expected = expectedValue ? someValue.to!string : ("not " ~ someValue.to!string); } return result(isSame, new ExpectedActualResult(expected, testData.to!string), file, line); } auto greaterThan()(const T someValue, const string file = __FILE__, const size_t line = __LINE__) if(!is(T == bool)) { validateException; addMessage(" greater than `"); addValue(someValue.to!string); addMessage("`"); beginCheck; auto isGreater = testData > someValue; auto mode = isGreater ? "greater than" : "less than or equal to"; auto expectedMode = isGreater ? "less than or equal to" : "greater than"; Message[] msg = [ Message(false, "`"), Message(true, testData.to!string), Message(false, "` is " ~ mode ~ " `"), Message(true, someValue.to!string), Message(false, "`.") ]; return result(isGreater, msg, new ExpectedActualResult(expectedMode ~ " `" ~ someValue.to!string ~ "`", testData.to!string), file, line); } auto lessThan()(const T someValue, const string file = __FILE__, const size_t line = __LINE__) if(!is(T == bool)) { validateException; addMessage(" less than `"); addValue(someValue.to!string); addMessage("`"); beginCheck; auto isLess = testData < someValue; Message[] msg = [ Message(false, "`"), Message(true, testData.to!string), Message(false, isLess ? "` is less than `" : "` is greater or equal to `"), Message(true, someValue.to!string), Message(false, "`.") ]; auto expectedMode = isLess ? "greater or equal to" : "less than"; return result(isLess, msg, new ExpectedActualResult(expectedMode ~ " `" ~ someValue.to!string ~ "`", testData.to!string), file, line); } auto between()(const T limit1, const T limit2, const string file = __FILE__, const size_t line = __LINE__) if(!is(T == bool)) { validateException; T min = limit1 < limit2 ? limit1 : limit2; T max = limit1 > limit2 ? limit1 : limit2; addMessage(" between `"); addValue(min.to!string); addMessage("` and `"); addValue(max.to!string); addMessage("`"); beginCheck; auto isLess = testData <= min; auto isGreater = testData >= max; auto isBetween = !isLess && !isGreater; Message[] msg; auto interval = "a value " ~ (expectedValue ? "inside" : "outside") ~ " (" ~ min.to!string ~ ", " ~ max.to!string ~ ") interval"; if(expectedValue) { msg ~= [ Message(false, "`"), Message(true, testData.to!string), Message(false, "`") ]; if(isLess) { msg ~= [ Message(false, " is less than or equal to `"), Message(true, min.to!string), Message(false, "`.") ]; } if(isGreater) { msg ~= [ Message(false, " is greater than or equal to `"), Message(true, max.to!string), Message(false, "`.") ]; } } return result(isBetween, msg, new ExpectedActualResult(interval, testData.to!string), file, line); } auto approximately()(const T someValue, const T delta, const string file = __FILE__, const size_t line = __LINE__) if(!is(T == bool)) { validateException; addMessage(" equal `"); addValue(someValue.to!string ~ "±" ~ delta.to!string); addMessage("`"); beginCheck; return between(someValue - delta, someValue + delta, file, line); } } /// When there is a lazy number that throws an it should throw that exception unittest { int someLazyInt() { throw new Exception("This is it."); } ({ someLazyInt.should.equal(3); }).should.throwAnyException.withMessage("This is it."); ({ someLazyInt.should.be.greaterThan(3); }).should.throwAnyException.withMessage("This is it."); ({ someLazyInt.should.be.lessThan(3); }).should.throwAnyException.withMessage("This is it."); ({ someLazyInt.should.be.between(3, 4); }).should.throwAnyException.withMessage("This is it."); ({ someLazyInt.should.be.approximately(3, 4); }).should.throwAnyException.withMessage("This is it."); } @("numbers equal") unittest { ({ 5.should.equal(5); 5.should.not.equal(6); }).should.not.throwAnyException; auto msg = ({ 5.should.equal(6); }).should.throwException!TestException.msg; msg.split("\n")[0].should.equal("5 should equal `6`."); msg.split("\n")[2].strip.should.equal("Expected:6"); msg.split("\n")[3].strip.should.equal("Actual:5"); msg = ({ 5.should.not.equal(5); }).should.throwException!TestException.msg; msg.split("\n")[0].should.equal("5 should not equal `5`."); msg.split("\n")[2].strip.should.equal("Expected:not 5"); msg.split("\n")[3].strip.should.equal("Actual:5"); } @("bools equal") unittest { ({ true.should.equal(true); true.should.not.equal(false); }).should.not.throwAnyException; auto msg = ({ true.should.equal(false); }).should.throwException!TestException.msg; msg.split("\n")[0].should.equal("true should equal `false`."); msg.split("\n")[2].strip.should.equal("Expected:false"); msg.split("\n")[3].strip.should.equal("Actual:true"); msg = ({ true.should.not.equal(true); }).should.throwException!TestException.msg; msg.split("\n")[0].should.equal("true should not equal `true`."); msg.split("\n")[2].strip.should.equal("Expected:false"); msg.split("\n")[3].strip.should.equal("Actual:true"); } @("numbers greater than") unittest { ({ 5.should.be.greaterThan(4); 5.should.not.be.greaterThan(6); 5.should.be.above(4); 5.should.not.be.above(6); }).should.not.throwAnyException; auto msg = ({ 5.should.be.greaterThan(5); 5.should.be.above(5); }).should.throwException!TestException.msg; msg.split("\n")[0].should.equal("5 should be greater than `5`. `5` is less than or equal to `5`."); msg.split("\n")[2].strip.should.equal("Expected:greater than `5`"); msg.split("\n")[3].strip.should.equal("Actual:5"); msg = ({ 5.should.not.be.greaterThan(4); 5.should.not.be.above(4); }).should.throwException!TestException.msg; msg.split("\n")[0].should.equal("5 should not be greater than `4`. `5` is greater than `4`."); msg.split("\n")[2].strip.should.equal("Expected:less than or equal to `4`"); msg.split("\n")[3].strip.should.equal("Actual:5"); } @("numbers less than") unittest { ({ 5.should.be.lessThan(6); 5.should.not.be.lessThan(4); 5.should.be.below(6); 5.should.not.be.below(4); }).should.not.throwAnyException; auto msg = ({ 5.should.be.lessThan(4); 5.should.be.below(4); }).should.throwException!TestException.msg; msg.split("\n")[0].should.equal("5 should be less than `4`. `5` is greater or equal to `4`."); msg.split("\n")[2].strip.should.equal("Expected:less than `4`"); msg.split("\n")[3].strip.should.equal("Actual:5"); msg = ({ 5.should.not.be.lessThan(6); 5.should.not.be.below(6); }).should.throwException!TestException.msg; msg.split("\n")[0].should.equal("5 should not be less than `6`. `5` is less than `6`."); } @("numbers between") unittest { ({ 5.should.be.between(4, 6); 5.should.be.between(6, 4); 5.should.not.be.between(5, 6); 5.should.not.be.between(4, 5); 5.should.be.within(4, 6); 5.should.be.within(6, 4); 5.should.not.be.within(5, 6); 5.should.not.be.within(4, 5); }).should.not.throwAnyException; auto msg = ({ 5.should.be.between(5, 6); 5.should.be.within(5, 6); }).should.throwException!TestException.msg; msg.split("\n")[0].should.equal("5 should be between `5` and `6`. `5` is less than or equal to `5`."); msg.split("\n")[2].strip.should.equal("Expected:a value inside (5, 6) interval"); msg.split("\n")[3].strip.should.equal("Actual:5"); msg = ({ 5.should.be.between(4, 5); 5.should.be.within(4, 5); }).should.throwException!TestException.msg; msg.split("\n")[0].should.equal("5 should be between `4` and `5`. `5` is greater than or equal to `5`."); msg.split("\n")[2].strip.should.equal("Expected:a value inside (4, 5) interval"); msg.split("\n")[3].strip.should.equal("Actual:5"); msg = ({ 5.should.not.be.between(4, 6); 5.should.not.be.within(4, 6); }).should.throwException!TestException.msg; msg.split("\n")[0].strip.should.equal("5 should not be between `4` and `6`."); msg.split("\n")[2].strip.should.equal("Expected:a value outside (4, 6) interval"); msg.split("\n")[3].strip.should.equal("Actual:5"); msg = ({ 5.should.not.be.between(6, 4); 5.should.not.be.within(6, 4); }).should.throwException!TestException.msg; msg.split("\n")[0].strip.should.equal("5 should not be between `4` and `6`."); msg.split("\n")[2].strip.should.equal("Expected:a value outside (4, 6) interval"); msg.split("\n")[3].strip.should.equal("Actual:5"); } @("numbers approximately") unittest { ({ (10f/3f).should.be.approximately(3, 0.34); (10f/3f).should.not.be.approximately(3, 0.24); }).should.not.throwAnyException; auto msg = ({ (10f/3f).should.be.approximately(3, 0.3); }).should.throwException!TestException.msg; msg.split("\n")[0].strip.should.equal("(10f/3f) should be equal `3±0.3`. `3.33333` is greater than or equal to `3.3`."); msg.split("\n")[2].strip.should.equal("Expected:a value inside (2.7, 3.3) interval"); msg.split("\n")[3].strip.should.equal("Actual:3.33333"); msg = ({ (10f/3f).should.not.be.approximately(3, 0.34); }).should.throwException!TestException.msg; msg.split("\n")[0].strip.should.equal("(10f/3f) should not be equal `3±0.34`."); msg.split("\n")[2].strip.should.equal("Expected:a value outside (2.66, 3.34) interval"); msg.split("\n")[3].strip.should.equal("Actual:3.33333"); } /// should throw exceptions for delegates that return basic types unittest { int value() { throw new Exception("not implemented"); } void voidValue() { throw new Exception("not implemented"); } void noException() { } value().should.throwAnyException.withMessage.equal("not implemented"); voidValue().should.throwAnyException.withMessage.equal("not implemented"); bool thrown; try { noException.should.throwAnyException; } catch (TestException e) { e.msg.should.startWith("noException should throw any exception. Nothing was thrown."); thrown = true; } thrown.should.equal(true); thrown = false; try { voidValue().should.not.throwAnyException; } catch(TestException e) { thrown = true; e.msg.split("\n")[0].should.equal("voidValue() should not throw any exception. An exception of type `object.Exception` saying `not implemented` was thrown."); } thrown.should.equal(true); } /// it should compile const comparison unittest { const actual = 42; actual.should.equal(42); }