1- using FsCheck . Xunit ;
21using FsCheck ;
2+ using FsCheck . Fluent ;
33
44public class DiamondTests
55{
@@ -8,118 +8,122 @@ public class DiamondTests
88
99 private static string LeadingSpaces ( string x ) => x . Substring ( 0 , x . IndexOfAny ( AllLetters ) ) ;
1010 private static string TrailingSpaces ( string x ) => x . Substring ( x . LastIndexOfAny ( AllLetters ) + 1 ) ;
11- private static char [ ] GetLetterRange ( char min , char max ) => Enumerable . Range ( min , max - min + 1 ) . Select ( i => ( char ) i ) . ToArray ( ) ;
1211
13- [ DiamondProperty ]
14- public void Diamond_is_not_empty ( char letter )
15- {
16- var actual = Diamond . Make ( letter ) ;
12+ private static char [ ] GetLetterRange ( char min , char max ) => Enumerable . Range ( min , max - min + 1 ) . Select ( i => ( char ) i ) . ToArray ( ) ;
1713
18- Assert . NotEmpty ( actual ) ;
14+ [ Fact ]
15+ public void Diamond_is_not_empty ( )
16+ {
17+ Prop . ForAll ( Letters , letter =>
18+ {
19+ var actual = Diamond . Make ( letter ) ;
20+ Assert . NotEmpty ( actual ) ;
21+ } ) . QuickCheckThrowOnFailure ( ) ;
1922 }
2023
21- [ DiamondProperty ( Skip = "Remove this Skip property to run this test" ) ]
22- public void First_row_contains_a ( char letter )
24+ [ Fact ( Skip = "Remove this Skip property to run this test" ) ]
25+ public void First_row_contains_a ( )
2326 {
24- var actual = Diamond . Make ( letter ) ;
25- var rows = Rows ( actual ) ;
26- var firstRowCharacters = rows . First ( ) . Trim ( ) ;
27+ Prop . ForAll ( Letters , letter =>
28+ {
29+ var actual = Diamond . Make ( letter ) ;
30+ var rows = Rows ( actual ) ;
31+ var firstRowCharacters = rows . First ( ) . Trim ( ) ;
2732
28- Assert . Equal ( "A" , firstRowCharacters ) ;
33+ Assert . Equal ( "A" , firstRowCharacters ) ;
34+ } ) . QuickCheckThrowOnFailure ( ) ;
2935 }
3036
31- [ DiamondProperty ( Skip = "Remove this Skip property to run this test" ) ]
32- public void All_rows_must_have_symmetric_contour ( char letter )
37+ [ Fact ( Skip = "Remove this Skip property to run this test" ) ]
38+ public void All_rows_must_have_symmetric_contour ( )
3339 {
34- var actual = Diamond . Make ( letter ) ;
35- var rows = Rows ( actual ) ;
36-
37- Assert . All ( rows , row =>
40+ Prop . ForAll ( Letters , letter =>
3841 {
39- Assert . Equal ( LeadingSpaces ( row ) , TrailingSpaces ( row ) ) ;
40- } ) ;
42+ var actual = Diamond . Make ( letter ) ;
43+ var rows = Rows ( actual ) ;
44+
45+ Assert . All ( rows , row => { Assert . Equal ( LeadingSpaces ( row ) , TrailingSpaces ( row ) ) ; } ) ;
46+ } ) . QuickCheckThrowOnFailure ( ) ;
4147 }
4248
43- [ DiamondProperty ( Skip = "Remove this Skip property to run this test" ) ]
44- public void Top_of_figure_has_letters_in_correct_order ( char letter )
49+ [ Fact ( Skip = "Remove this Skip property to run this test" ) ]
50+ public void Top_of_figure_has_letters_in_correct_order ( )
4551 {
46- var actual = Diamond . Make ( letter ) ;
47- var rows = Rows ( actual ) ;
52+ Prop . ForAll ( Letters , letter =>
53+ {
54+ var actual = Diamond . Make ( letter ) ;
55+ var rows = Rows ( actual ) ;
4856
49- var expected = GetLetterRange ( 'A' , letter ) ;
50- var firstNonSpaceLetters = rows . Take ( expected . Length ) . Select ( row => row . Trim ( ) [ 0 ] ) ;
57+ var expected = GetLetterRange ( 'A' , letter ) ;
58+ var firstNonSpaceLetters = rows . Take ( expected . Length ) . Select ( row => row . Trim ( ) [ 0 ] ) ;
5159
52- Assert . Equal ( firstNonSpaceLetters , expected ) ;
60+ Assert . Equal ( firstNonSpaceLetters , expected ) ;
61+ } ) . QuickCheckThrowOnFailure ( ) ;
5362 }
5463
55- [ DiamondProperty ( Skip = "Remove this Skip property to run this test" ) ]
56- public void Figure_is_symmetric_around_the_horizontal_axis ( char letter )
64+ [ Fact ( Skip = "Remove this Skip property to run this test" ) ]
65+ public void Figure_is_symmetric_around_the_horizontal_axis ( )
5766 {
58- var actual = Diamond . Make ( letter ) ;
67+ Prop . ForAll ( Letters , letter =>
68+ {
69+ var actual = Diamond . Make ( letter ) ;
5970
60- var rows = Rows ( actual ) ;
61- var top = rows . TakeWhile ( row => ! row . Contains ( letter ) ) ;
62- var bottom = rows . Reverse ( ) . TakeWhile ( row => ! row . Contains ( letter ) ) ;
71+ var rows = Rows ( actual ) ;
72+ var top = rows . TakeWhile ( row => ! row . Contains ( letter ) ) ;
73+ var bottom = rows . Reverse ( ) . TakeWhile ( row => ! row . Contains ( letter ) ) ;
6374
64- Assert . Equal ( bottom , top ) ;
75+ Assert . Equal ( bottom , top ) ;
76+ } ) . QuickCheckThrowOnFailure ( ) ;
6577 }
6678
67- [ DiamondProperty ( Skip = "Remove this Skip property to run this test" ) ]
68- public void Diamond_has_square_shape ( char letter )
79+ [ Fact ( Skip = "Remove this Skip property to run this test" ) ]
80+ public void Diamond_has_square_shape ( )
6981 {
70- var actual = Diamond . Make ( letter ) ;
82+ Prop . ForAll ( Letters , letter =>
83+ {
84+ var actual = Diamond . Make ( letter ) ;
7185
72- var rows = Rows ( actual ) ;
73- var expected = rows . Length ;
86+ var rows = Rows ( actual ) ;
87+ var expected = rows . Length ;
7488
75- Assert . All ( rows , row =>
76- {
77- Assert . Equal ( expected , row . Length ) ;
78- } ) ;
89+ Assert . All ( rows , row => { Assert . Equal ( expected , row . Length ) ; } ) ;
90+ } ) . QuickCheckThrowOnFailure ( ) ;
7991 }
8092
81- [ DiamondProperty ( Skip = "Remove this Skip property to run this test" ) ]
82- public void All_rows_except_top_and_bottom_have_two_identical_letters ( char letter )
93+ [ Fact ( Skip = "Remove this Skip property to run this test" ) ]
94+ public void All_rows_except_top_and_bottom_have_two_identical_letters ( )
8395 {
84- var actual = Diamond . Make ( letter ) ;
96+ Prop . ForAll ( Letters , letter =>
97+ {
98+ var actual = Diamond . Make ( letter ) ;
8599
86- var rows = Rows ( actual ) . Where ( row => ! row . Contains ( 'A' ) ) ;
100+ var rows = Rows ( actual ) . Where ( row => ! row . Contains ( 'A' ) ) ;
87101
88- Assert . All ( rows , row =>
89- {
90- var twoCharacters = row . Replace ( " " , "" ) . Length == 2 ;
91- var identicalCharacters = row . Replace ( " " , "" ) . Distinct ( ) . Count ( ) == 1 ;
92- Assert . True ( twoCharacters && identicalCharacters , "Does not have two identical letters" ) ;
93- } ) ;
102+ Assert . All ( rows , row =>
103+ {
104+ var twoCharacters = row . Replace ( " " , "" ) . Length == 2 ;
105+ var identicalCharacters = row . Replace ( " " , "" ) . Distinct ( ) . Count ( ) == 1 ;
106+ Assert . True ( twoCharacters && identicalCharacters , "Does not have two identical letters" ) ;
107+ } ) ;
108+ } ) . QuickCheckThrowOnFailure ( ) ;
94109 }
95110
96- [ DiamondProperty ( Skip = "Remove this Skip property to run this test" ) ]
97- public void Bottom_left_corner_spaces_are_triangle ( char letter )
111+ [ Fact ( Skip = "Remove this Skip property to run this test" ) ]
112+ public void Bottom_left_corner_spaces_are_triangle ( )
98113 {
99- var actual = Diamond . Make ( letter ) ;
100-
101- var rows = Rows ( actual ) ;
114+ Prop . ForAll ( Letters , letter =>
115+ {
116+ var actual = Diamond . Make ( letter ) ;
102117
103- var cornerSpaces = rows . Reverse ( ) . SkipWhile ( row => ! row . Contains ( letter ) ) . Select ( LeadingSpaces ) ;
104- var spaceCounts = cornerSpaces . Select ( row => row . Length ) . ToList ( ) ;
105- var expected = Enumerable . Range ( 0 , spaceCounts . Count ) . Select ( i => i ) . ToList ( ) ;
118+ var rows = Rows ( actual ) ;
106119
107- Assert . Equal ( expected , spaceCounts ) ;
108- }
109- }
120+ var cornerSpaces = rows . Reverse ( ) . SkipWhile ( row => ! row . Contains ( letter ) ) . Select ( LeadingSpaces ) ;
121+ var spaceCounts = cornerSpaces . Select ( row => row . Length ) . ToList ( ) ;
122+ var expected = Enumerable . Range ( 0 , spaceCounts . Count ) . Select ( i => i ) . ToList ( ) ;
110123
111- public class DiamondPropertyAttribute : PropertyAttribute
112- {
113- public DiamondPropertyAttribute ( )
114- {
115- Arbitrary = new [ ] { typeof ( LettersOnlyStringArbitrary ) } ;
124+ Assert . Equal ( expected , spaceCounts ) ;
125+ } ) . QuickCheckThrowOnFailure ( ) ;
116126 }
117- }
118127
119- public static class LettersOnlyStringArbitrary
120- {
121- public static Arbitrary < char > Chars ( )
122- {
123- return Arb . Default . Char ( ) . Filter ( x => x >= 'A' && x <= 'Z' ) ;
124- }
125- }
128+ private static readonly Arbitrary < char > Letters = Gen . Elements ( "ABCDEFGHIJKLMNOPQRSTUVWXYZ" . ToCharArray ( ) ) . ToArbitrary ( ) ;
129+ }
0 commit comments