diff --git a/build.ps1 b/build.ps1 index 2a2706a8bf..1299bd1585 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,5 +1,5 @@ -$CakeVersion = "0.18.0" -$DotNetVersion = "1.0.1"; +$CakeVersion = "0.20.0" +$DotNetVersion = "1.0.4"; $DotNetInstallerUri = "https://dot.net/v1/dotnet-install.ps1"; # Make sure tools folder exists diff --git a/build.sh b/build.sh index 53b611e53f..d3f79d470d 100755 --- a/build.sh +++ b/build.sh @@ -3,9 +3,9 @@ # Define directories. SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) TOOLS_DIR=$SCRIPT_DIR/tools -CAKE_VERSION=0.18.0 +CAKE_VERSION=0.20.0 CAKE_DLL=$TOOLS_DIR/Cake.CoreCLR.$CAKE_VERSION/Cake.dll -DOTNET_VERSION=1.0.1 +DOTNET_VERSION=1.0.4 # Make sure the tools folder exist. if [ ! -d "$TOOLS_DIR" ]; then diff --git a/exercises/beer-song/BeerSongTest.cs b/exercises/beer-song/BeerSongTest.cs index bc1dcf5f22..cd3341390a 100755 --- a/exercises/beer-song/BeerSongTest.cs +++ b/exercises/beer-song/BeerSongTest.cs @@ -8,8 +8,8 @@ public class BeerSongTest public void First_generic_verse() { var expected = - "99 bottles of beer on the wall, 99 bottles of beer.\n"+ - "Take one down and pass it around, 98 bottles of beer on the wall.\n"+ + "99 bottles of beer on the wall, 99 bottles of beer.\n" + + "Take one down and pass it around, 98 bottles of beer on the wall.\n" + ""; Assert.Equal(expected, BeerSong.Verse(99)); } @@ -18,8 +18,8 @@ public void First_generic_verse() public void Last_generic_verse() { var expected = - "3 bottles of beer on the wall, 3 bottles of beer.\n"+ - "Take one down and pass it around, 2 bottles of beer on the wall.\n"+ + "3 bottles of beer on the wall, 3 bottles of beer.\n" + + "Take one down and pass it around, 2 bottles of beer on the wall.\n" + ""; Assert.Equal(expected, BeerSong.Verse(3)); } @@ -28,8 +28,8 @@ public void Last_generic_verse() public void Verse_2() { var expected = - "2 bottles of beer on the wall, 2 bottles of beer.\n"+ - "Take one down and pass it around, 1 bottle of beer on the wall.\n"+ + "2 bottles of beer on the wall, 2 bottles of beer.\n" + + "Take one down and pass it around, 1 bottle of beer on the wall.\n" + ""; Assert.Equal(expected, BeerSong.Verse(2)); } @@ -38,8 +38,8 @@ public void Verse_2() public void Verse_1() { var expected = - "1 bottle of beer on the wall, 1 bottle of beer.\n"+ - "Take it down and pass it around, no more bottles of beer on the wall.\n"+ + "1 bottle of beer on the wall, 1 bottle of beer.\n" + + "Take it down and pass it around, no more bottles of beer on the wall.\n" + ""; Assert.Equal(expected, BeerSong.Verse(1)); } @@ -48,8 +48,8 @@ public void Verse_1() public void Verse_0() { var expected = - "No more bottles of beer on the wall, no more bottles of beer.\n"+ - "Go to the store and buy some more, 99 bottles of beer on the wall.\n"+ + "No more bottles of beer on the wall, no more bottles of beer.\n" + + "Go to the store and buy some more, 99 bottles of beer on the wall.\n" + ""; Assert.Equal(expected, BeerSong.Verse(0)); } @@ -58,11 +58,11 @@ public void Verse_0() public void First_two_verses() { var expected = - "99 bottles of beer on the wall, 99 bottles of beer.\n"+ - "Take one down and pass it around, 98 bottles of beer on the wall.\n"+ - "\n"+ - "98 bottles of beer on the wall, 98 bottles of beer.\n"+ - "Take one down and pass it around, 97 bottles of beer on the wall.\n"+ + "99 bottles of beer on the wall, 99 bottles of beer.\n" + + "Take one down and pass it around, 98 bottles of beer on the wall.\n" + + "\n" + + "98 bottles of beer on the wall, 98 bottles of beer.\n" + + "Take one down and pass it around, 97 bottles of beer on the wall.\n" + ""; Assert.Equal(expected, BeerSong.Verses(99, 98)); } @@ -71,14 +71,14 @@ public void First_two_verses() public void Last_three_verses() { var expected = - "2 bottles of beer on the wall, 2 bottles of beer.\n"+ - "Take one down and pass it around, 1 bottle of beer on the wall.\n"+ - "\n"+ - "1 bottle of beer on the wall, 1 bottle of beer.\n"+ - "Take it down and pass it around, no more bottles of beer on the wall.\n"+ - "\n"+ - "No more bottles of beer on the wall, no more bottles of beer.\n"+ - "Go to the store and buy some more, 99 bottles of beer on the wall.\n"+ + "2 bottles of beer on the wall, 2 bottles of beer.\n" + + "Take one down and pass it around, 1 bottle of beer on the wall.\n" + + "\n" + + "1 bottle of beer on the wall, 1 bottle of beer.\n" + + "Take it down and pass it around, no more bottles of beer on the wall.\n" + + "\n" + + "No more bottles of beer on the wall, no more bottles of beer.\n" + + "Go to the store and buy some more, 99 bottles of beer on the wall.\n" + ""; Assert.Equal(expected, BeerSong.Verses(2, 0)); } @@ -87,305 +87,305 @@ public void Last_three_verses() public void All_verses() { var expected = - "99 bottles of beer on the wall, 99 bottles of beer.\n"+ - "Take one down and pass it around, 98 bottles of beer on the wall.\n"+ - "\n"+ - "98 bottles of beer on the wall, 98 bottles of beer.\n"+ - "Take one down and pass it around, 97 bottles of beer on the wall.\n"+ - "\n"+ - "97 bottles of beer on the wall, 97 bottles of beer.\n"+ - "Take one down and pass it around, 96 bottles of beer on the wall.\n"+ - "\n"+ - "96 bottles of beer on the wall, 96 bottles of beer.\n"+ - "Take one down and pass it around, 95 bottles of beer on the wall.\n"+ - "\n"+ - "95 bottles of beer on the wall, 95 bottles of beer.\n"+ - "Take one down and pass it around, 94 bottles of beer on the wall.\n"+ - "\n"+ - "94 bottles of beer on the wall, 94 bottles of beer.\n"+ - "Take one down and pass it around, 93 bottles of beer on the wall.\n"+ - "\n"+ - "93 bottles of beer on the wall, 93 bottles of beer.\n"+ - "Take one down and pass it around, 92 bottles of beer on the wall.\n"+ - "\n"+ - "92 bottles of beer on the wall, 92 bottles of beer.\n"+ - "Take one down and pass it around, 91 bottles of beer on the wall.\n"+ - "\n"+ - "91 bottles of beer on the wall, 91 bottles of beer.\n"+ - "Take one down and pass it around, 90 bottles of beer on the wall.\n"+ - "\n"+ - "90 bottles of beer on the wall, 90 bottles of beer.\n"+ - "Take one down and pass it around, 89 bottles of beer on the wall.\n"+ - "\n"+ - "89 bottles of beer on the wall, 89 bottles of beer.\n"+ - "Take one down and pass it around, 88 bottles of beer on the wall.\n"+ - "\n"+ - "88 bottles of beer on the wall, 88 bottles of beer.\n"+ - "Take one down and pass it around, 87 bottles of beer on the wall.\n"+ - "\n"+ - "87 bottles of beer on the wall, 87 bottles of beer.\n"+ - "Take one down and pass it around, 86 bottles of beer on the wall.\n"+ - "\n"+ - "86 bottles of beer on the wall, 86 bottles of beer.\n"+ - "Take one down and pass it around, 85 bottles of beer on the wall.\n"+ - "\n"+ - "85 bottles of beer on the wall, 85 bottles of beer.\n"+ - "Take one down and pass it around, 84 bottles of beer on the wall.\n"+ - "\n"+ - "84 bottles of beer on the wall, 84 bottles of beer.\n"+ - "Take one down and pass it around, 83 bottles of beer on the wall.\n"+ - "\n"+ - "83 bottles of beer on the wall, 83 bottles of beer.\n"+ - "Take one down and pass it around, 82 bottles of beer on the wall.\n"+ - "\n"+ - "82 bottles of beer on the wall, 82 bottles of beer.\n"+ - "Take one down and pass it around, 81 bottles of beer on the wall.\n"+ - "\n"+ - "81 bottles of beer on the wall, 81 bottles of beer.\n"+ - "Take one down and pass it around, 80 bottles of beer on the wall.\n"+ - "\n"+ - "80 bottles of beer on the wall, 80 bottles of beer.\n"+ - "Take one down and pass it around, 79 bottles of beer on the wall.\n"+ - "\n"+ - "79 bottles of beer on the wall, 79 bottles of beer.\n"+ - "Take one down and pass it around, 78 bottles of beer on the wall.\n"+ - "\n"+ - "78 bottles of beer on the wall, 78 bottles of beer.\n"+ - "Take one down and pass it around, 77 bottles of beer on the wall.\n"+ - "\n"+ - "77 bottles of beer on the wall, 77 bottles of beer.\n"+ - "Take one down and pass it around, 76 bottles of beer on the wall.\n"+ - "\n"+ - "76 bottles of beer on the wall, 76 bottles of beer.\n"+ - "Take one down and pass it around, 75 bottles of beer on the wall.\n"+ - "\n"+ - "75 bottles of beer on the wall, 75 bottles of beer.\n"+ - "Take one down and pass it around, 74 bottles of beer on the wall.\n"+ - "\n"+ - "74 bottles of beer on the wall, 74 bottles of beer.\n"+ - "Take one down and pass it around, 73 bottles of beer on the wall.\n"+ - "\n"+ - "73 bottles of beer on the wall, 73 bottles of beer.\n"+ - "Take one down and pass it around, 72 bottles of beer on the wall.\n"+ - "\n"+ - "72 bottles of beer on the wall, 72 bottles of beer.\n"+ - "Take one down and pass it around, 71 bottles of beer on the wall.\n"+ - "\n"+ - "71 bottles of beer on the wall, 71 bottles of beer.\n"+ - "Take one down and pass it around, 70 bottles of beer on the wall.\n"+ - "\n"+ - "70 bottles of beer on the wall, 70 bottles of beer.\n"+ - "Take one down and pass it around, 69 bottles of beer on the wall.\n"+ - "\n"+ - "69 bottles of beer on the wall, 69 bottles of beer.\n"+ - "Take one down and pass it around, 68 bottles of beer on the wall.\n"+ - "\n"+ - "68 bottles of beer on the wall, 68 bottles of beer.\n"+ - "Take one down and pass it around, 67 bottles of beer on the wall.\n"+ - "\n"+ - "67 bottles of beer on the wall, 67 bottles of beer.\n"+ - "Take one down and pass it around, 66 bottles of beer on the wall.\n"+ - "\n"+ - "66 bottles of beer on the wall, 66 bottles of beer.\n"+ - "Take one down and pass it around, 65 bottles of beer on the wall.\n"+ - "\n"+ - "65 bottles of beer on the wall, 65 bottles of beer.\n"+ - "Take one down and pass it around, 64 bottles of beer on the wall.\n"+ - "\n"+ - "64 bottles of beer on the wall, 64 bottles of beer.\n"+ - "Take one down and pass it around, 63 bottles of beer on the wall.\n"+ - "\n"+ - "63 bottles of beer on the wall, 63 bottles of beer.\n"+ - "Take one down and pass it around, 62 bottles of beer on the wall.\n"+ - "\n"+ - "62 bottles of beer on the wall, 62 bottles of beer.\n"+ - "Take one down and pass it around, 61 bottles of beer on the wall.\n"+ - "\n"+ - "61 bottles of beer on the wall, 61 bottles of beer.\n"+ - "Take one down and pass it around, 60 bottles of beer on the wall.\n"+ - "\n"+ - "60 bottles of beer on the wall, 60 bottles of beer.\n"+ - "Take one down and pass it around, 59 bottles of beer on the wall.\n"+ - "\n"+ - "59 bottles of beer on the wall, 59 bottles of beer.\n"+ - "Take one down and pass it around, 58 bottles of beer on the wall.\n"+ - "\n"+ - "58 bottles of beer on the wall, 58 bottles of beer.\n"+ - "Take one down and pass it around, 57 bottles of beer on the wall.\n"+ - "\n"+ - "57 bottles of beer on the wall, 57 bottles of beer.\n"+ - "Take one down and pass it around, 56 bottles of beer on the wall.\n"+ - "\n"+ - "56 bottles of beer on the wall, 56 bottles of beer.\n"+ - "Take one down and pass it around, 55 bottles of beer on the wall.\n"+ - "\n"+ - "55 bottles of beer on the wall, 55 bottles of beer.\n"+ - "Take one down and pass it around, 54 bottles of beer on the wall.\n"+ - "\n"+ - "54 bottles of beer on the wall, 54 bottles of beer.\n"+ - "Take one down and pass it around, 53 bottles of beer on the wall.\n"+ - "\n"+ - "53 bottles of beer on the wall, 53 bottles of beer.\n"+ - "Take one down and pass it around, 52 bottles of beer on the wall.\n"+ - "\n"+ - "52 bottles of beer on the wall, 52 bottles of beer.\n"+ - "Take one down and pass it around, 51 bottles of beer on the wall.\n"+ - "\n"+ - "51 bottles of beer on the wall, 51 bottles of beer.\n"+ - "Take one down and pass it around, 50 bottles of beer on the wall.\n"+ - "\n"+ - "50 bottles of beer on the wall, 50 bottles of beer.\n"+ - "Take one down and pass it around, 49 bottles of beer on the wall.\n"+ - "\n"+ - "49 bottles of beer on the wall, 49 bottles of beer.\n"+ - "Take one down and pass it around, 48 bottles of beer on the wall.\n"+ - "\n"+ - "48 bottles of beer on the wall, 48 bottles of beer.\n"+ - "Take one down and pass it around, 47 bottles of beer on the wall.\n"+ - "\n"+ - "47 bottles of beer on the wall, 47 bottles of beer.\n"+ - "Take one down and pass it around, 46 bottles of beer on the wall.\n"+ - "\n"+ - "46 bottles of beer on the wall, 46 bottles of beer.\n"+ - "Take one down and pass it around, 45 bottles of beer on the wall.\n"+ - "\n"+ - "45 bottles of beer on the wall, 45 bottles of beer.\n"+ - "Take one down and pass it around, 44 bottles of beer on the wall.\n"+ - "\n"+ - "44 bottles of beer on the wall, 44 bottles of beer.\n"+ - "Take one down and pass it around, 43 bottles of beer on the wall.\n"+ - "\n"+ - "43 bottles of beer on the wall, 43 bottles of beer.\n"+ - "Take one down and pass it around, 42 bottles of beer on the wall.\n"+ - "\n"+ - "42 bottles of beer on the wall, 42 bottles of beer.\n"+ - "Take one down and pass it around, 41 bottles of beer on the wall.\n"+ - "\n"+ - "41 bottles of beer on the wall, 41 bottles of beer.\n"+ - "Take one down and pass it around, 40 bottles of beer on the wall.\n"+ - "\n"+ - "40 bottles of beer on the wall, 40 bottles of beer.\n"+ - "Take one down and pass it around, 39 bottles of beer on the wall.\n"+ - "\n"+ - "39 bottles of beer on the wall, 39 bottles of beer.\n"+ - "Take one down and pass it around, 38 bottles of beer on the wall.\n"+ - "\n"+ - "38 bottles of beer on the wall, 38 bottles of beer.\n"+ - "Take one down and pass it around, 37 bottles of beer on the wall.\n"+ - "\n"+ - "37 bottles of beer on the wall, 37 bottles of beer.\n"+ - "Take one down and pass it around, 36 bottles of beer on the wall.\n"+ - "\n"+ - "36 bottles of beer on the wall, 36 bottles of beer.\n"+ - "Take one down and pass it around, 35 bottles of beer on the wall.\n"+ - "\n"+ - "35 bottles of beer on the wall, 35 bottles of beer.\n"+ - "Take one down and pass it around, 34 bottles of beer on the wall.\n"+ - "\n"+ - "34 bottles of beer on the wall, 34 bottles of beer.\n"+ - "Take one down and pass it around, 33 bottles of beer on the wall.\n"+ - "\n"+ - "33 bottles of beer on the wall, 33 bottles of beer.\n"+ - "Take one down and pass it around, 32 bottles of beer on the wall.\n"+ - "\n"+ - "32 bottles of beer on the wall, 32 bottles of beer.\n"+ - "Take one down and pass it around, 31 bottles of beer on the wall.\n"+ - "\n"+ - "31 bottles of beer on the wall, 31 bottles of beer.\n"+ - "Take one down and pass it around, 30 bottles of beer on the wall.\n"+ - "\n"+ - "30 bottles of beer on the wall, 30 bottles of beer.\n"+ - "Take one down and pass it around, 29 bottles of beer on the wall.\n"+ - "\n"+ - "29 bottles of beer on the wall, 29 bottles of beer.\n"+ - "Take one down and pass it around, 28 bottles of beer on the wall.\n"+ - "\n"+ - "28 bottles of beer on the wall, 28 bottles of beer.\n"+ - "Take one down and pass it around, 27 bottles of beer on the wall.\n"+ - "\n"+ - "27 bottles of beer on the wall, 27 bottles of beer.\n"+ - "Take one down and pass it around, 26 bottles of beer on the wall.\n"+ - "\n"+ - "26 bottles of beer on the wall, 26 bottles of beer.\n"+ - "Take one down and pass it around, 25 bottles of beer on the wall.\n"+ - "\n"+ - "25 bottles of beer on the wall, 25 bottles of beer.\n"+ - "Take one down and pass it around, 24 bottles of beer on the wall.\n"+ - "\n"+ - "24 bottles of beer on the wall, 24 bottles of beer.\n"+ - "Take one down and pass it around, 23 bottles of beer on the wall.\n"+ - "\n"+ - "23 bottles of beer on the wall, 23 bottles of beer.\n"+ - "Take one down and pass it around, 22 bottles of beer on the wall.\n"+ - "\n"+ - "22 bottles of beer on the wall, 22 bottles of beer.\n"+ - "Take one down and pass it around, 21 bottles of beer on the wall.\n"+ - "\n"+ - "21 bottles of beer on the wall, 21 bottles of beer.\n"+ - "Take one down and pass it around, 20 bottles of beer on the wall.\n"+ - "\n"+ - "20 bottles of beer on the wall, 20 bottles of beer.\n"+ - "Take one down and pass it around, 19 bottles of beer on the wall.\n"+ - "\n"+ - "19 bottles of beer on the wall, 19 bottles of beer.\n"+ - "Take one down and pass it around, 18 bottles of beer on the wall.\n"+ - "\n"+ - "18 bottles of beer on the wall, 18 bottles of beer.\n"+ - "Take one down and pass it around, 17 bottles of beer on the wall.\n"+ - "\n"+ - "17 bottles of beer on the wall, 17 bottles of beer.\n"+ - "Take one down and pass it around, 16 bottles of beer on the wall.\n"+ - "\n"+ - "16 bottles of beer on the wall, 16 bottles of beer.\n"+ - "Take one down and pass it around, 15 bottles of beer on the wall.\n"+ - "\n"+ - "15 bottles of beer on the wall, 15 bottles of beer.\n"+ - "Take one down and pass it around, 14 bottles of beer on the wall.\n"+ - "\n"+ - "14 bottles of beer on the wall, 14 bottles of beer.\n"+ - "Take one down and pass it around, 13 bottles of beer on the wall.\n"+ - "\n"+ - "13 bottles of beer on the wall, 13 bottles of beer.\n"+ - "Take one down and pass it around, 12 bottles of beer on the wall.\n"+ - "\n"+ - "12 bottles of beer on the wall, 12 bottles of beer.\n"+ - "Take one down and pass it around, 11 bottles of beer on the wall.\n"+ - "\n"+ - "11 bottles of beer on the wall, 11 bottles of beer.\n"+ - "Take one down and pass it around, 10 bottles of beer on the wall.\n"+ - "\n"+ - "10 bottles of beer on the wall, 10 bottles of beer.\n"+ - "Take one down and pass it around, 9 bottles of beer on the wall.\n"+ - "\n"+ - "9 bottles of beer on the wall, 9 bottles of beer.\n"+ - "Take one down and pass it around, 8 bottles of beer on the wall.\n"+ - "\n"+ - "8 bottles of beer on the wall, 8 bottles of beer.\n"+ - "Take one down and pass it around, 7 bottles of beer on the wall.\n"+ - "\n"+ - "7 bottles of beer on the wall, 7 bottles of beer.\n"+ - "Take one down and pass it around, 6 bottles of beer on the wall.\n"+ - "\n"+ - "6 bottles of beer on the wall, 6 bottles of beer.\n"+ - "Take one down and pass it around, 5 bottles of beer on the wall.\n"+ - "\n"+ - "5 bottles of beer on the wall, 5 bottles of beer.\n"+ - "Take one down and pass it around, 4 bottles of beer on the wall.\n"+ - "\n"+ - "4 bottles of beer on the wall, 4 bottles of beer.\n"+ - "Take one down and pass it around, 3 bottles of beer on the wall.\n"+ - "\n"+ - "3 bottles of beer on the wall, 3 bottles of beer.\n"+ - "Take one down and pass it around, 2 bottles of beer on the wall.\n"+ - "\n"+ - "2 bottles of beer on the wall, 2 bottles of beer.\n"+ - "Take one down and pass it around, 1 bottle of beer on the wall.\n"+ - "\n"+ - "1 bottle of beer on the wall, 1 bottle of beer.\n"+ - "Take it down and pass it around, no more bottles of beer on the wall.\n"+ - "\n"+ - "No more bottles of beer on the wall, no more bottles of beer.\n"+ - "Go to the store and buy some more, 99 bottles of beer on the wall.\n"+ + "99 bottles of beer on the wall, 99 bottles of beer.\n" + + "Take one down and pass it around, 98 bottles of beer on the wall.\n" + + "\n" + + "98 bottles of beer on the wall, 98 bottles of beer.\n" + + "Take one down and pass it around, 97 bottles of beer on the wall.\n" + + "\n" + + "97 bottles of beer on the wall, 97 bottles of beer.\n" + + "Take one down and pass it around, 96 bottles of beer on the wall.\n" + + "\n" + + "96 bottles of beer on the wall, 96 bottles of beer.\n" + + "Take one down and pass it around, 95 bottles of beer on the wall.\n" + + "\n" + + "95 bottles of beer on the wall, 95 bottles of beer.\n" + + "Take one down and pass it around, 94 bottles of beer on the wall.\n" + + "\n" + + "94 bottles of beer on the wall, 94 bottles of beer.\n" + + "Take one down and pass it around, 93 bottles of beer on the wall.\n" + + "\n" + + "93 bottles of beer on the wall, 93 bottles of beer.\n" + + "Take one down and pass it around, 92 bottles of beer on the wall.\n" + + "\n" + + "92 bottles of beer on the wall, 92 bottles of beer.\n" + + "Take one down and pass it around, 91 bottles of beer on the wall.\n" + + "\n" + + "91 bottles of beer on the wall, 91 bottles of beer.\n" + + "Take one down and pass it around, 90 bottles of beer on the wall.\n" + + "\n" + + "90 bottles of beer on the wall, 90 bottles of beer.\n" + + "Take one down and pass it around, 89 bottles of beer on the wall.\n" + + "\n" + + "89 bottles of beer on the wall, 89 bottles of beer.\n" + + "Take one down and pass it around, 88 bottles of beer on the wall.\n" + + "\n" + + "88 bottles of beer on the wall, 88 bottles of beer.\n" + + "Take one down and pass it around, 87 bottles of beer on the wall.\n" + + "\n" + + "87 bottles of beer on the wall, 87 bottles of beer.\n" + + "Take one down and pass it around, 86 bottles of beer on the wall.\n" + + "\n" + + "86 bottles of beer on the wall, 86 bottles of beer.\n" + + "Take one down and pass it around, 85 bottles of beer on the wall.\n" + + "\n" + + "85 bottles of beer on the wall, 85 bottles of beer.\n" + + "Take one down and pass it around, 84 bottles of beer on the wall.\n" + + "\n" + + "84 bottles of beer on the wall, 84 bottles of beer.\n" + + "Take one down and pass it around, 83 bottles of beer on the wall.\n" + + "\n" + + "83 bottles of beer on the wall, 83 bottles of beer.\n" + + "Take one down and pass it around, 82 bottles of beer on the wall.\n" + + "\n" + + "82 bottles of beer on the wall, 82 bottles of beer.\n" + + "Take one down and pass it around, 81 bottles of beer on the wall.\n" + + "\n" + + "81 bottles of beer on the wall, 81 bottles of beer.\n" + + "Take one down and pass it around, 80 bottles of beer on the wall.\n" + + "\n" + + "80 bottles of beer on the wall, 80 bottles of beer.\n" + + "Take one down and pass it around, 79 bottles of beer on the wall.\n" + + "\n" + + "79 bottles of beer on the wall, 79 bottles of beer.\n" + + "Take one down and pass it around, 78 bottles of beer on the wall.\n" + + "\n" + + "78 bottles of beer on the wall, 78 bottles of beer.\n" + + "Take one down and pass it around, 77 bottles of beer on the wall.\n" + + "\n" + + "77 bottles of beer on the wall, 77 bottles of beer.\n" + + "Take one down and pass it around, 76 bottles of beer on the wall.\n" + + "\n" + + "76 bottles of beer on the wall, 76 bottles of beer.\n" + + "Take one down and pass it around, 75 bottles of beer on the wall.\n" + + "\n" + + "75 bottles of beer on the wall, 75 bottles of beer.\n" + + "Take one down and pass it around, 74 bottles of beer on the wall.\n" + + "\n" + + "74 bottles of beer on the wall, 74 bottles of beer.\n" + + "Take one down and pass it around, 73 bottles of beer on the wall.\n" + + "\n" + + "73 bottles of beer on the wall, 73 bottles of beer.\n" + + "Take one down and pass it around, 72 bottles of beer on the wall.\n" + + "\n" + + "72 bottles of beer on the wall, 72 bottles of beer.\n" + + "Take one down and pass it around, 71 bottles of beer on the wall.\n" + + "\n" + + "71 bottles of beer on the wall, 71 bottles of beer.\n" + + "Take one down and pass it around, 70 bottles of beer on the wall.\n" + + "\n" + + "70 bottles of beer on the wall, 70 bottles of beer.\n" + + "Take one down and pass it around, 69 bottles of beer on the wall.\n" + + "\n" + + "69 bottles of beer on the wall, 69 bottles of beer.\n" + + "Take one down and pass it around, 68 bottles of beer on the wall.\n" + + "\n" + + "68 bottles of beer on the wall, 68 bottles of beer.\n" + + "Take one down and pass it around, 67 bottles of beer on the wall.\n" + + "\n" + + "67 bottles of beer on the wall, 67 bottles of beer.\n" + + "Take one down and pass it around, 66 bottles of beer on the wall.\n" + + "\n" + + "66 bottles of beer on the wall, 66 bottles of beer.\n" + + "Take one down and pass it around, 65 bottles of beer on the wall.\n" + + "\n" + + "65 bottles of beer on the wall, 65 bottles of beer.\n" + + "Take one down and pass it around, 64 bottles of beer on the wall.\n" + + "\n" + + "64 bottles of beer on the wall, 64 bottles of beer.\n" + + "Take one down and pass it around, 63 bottles of beer on the wall.\n" + + "\n" + + "63 bottles of beer on the wall, 63 bottles of beer.\n" + + "Take one down and pass it around, 62 bottles of beer on the wall.\n" + + "\n" + + "62 bottles of beer on the wall, 62 bottles of beer.\n" + + "Take one down and pass it around, 61 bottles of beer on the wall.\n" + + "\n" + + "61 bottles of beer on the wall, 61 bottles of beer.\n" + + "Take one down and pass it around, 60 bottles of beer on the wall.\n" + + "\n" + + "60 bottles of beer on the wall, 60 bottles of beer.\n" + + "Take one down and pass it around, 59 bottles of beer on the wall.\n" + + "\n" + + "59 bottles of beer on the wall, 59 bottles of beer.\n" + + "Take one down and pass it around, 58 bottles of beer on the wall.\n" + + "\n" + + "58 bottles of beer on the wall, 58 bottles of beer.\n" + + "Take one down and pass it around, 57 bottles of beer on the wall.\n" + + "\n" + + "57 bottles of beer on the wall, 57 bottles of beer.\n" + + "Take one down and pass it around, 56 bottles of beer on the wall.\n" + + "\n" + + "56 bottles of beer on the wall, 56 bottles of beer.\n" + + "Take one down and pass it around, 55 bottles of beer on the wall.\n" + + "\n" + + "55 bottles of beer on the wall, 55 bottles of beer.\n" + + "Take one down and pass it around, 54 bottles of beer on the wall.\n" + + "\n" + + "54 bottles of beer on the wall, 54 bottles of beer.\n" + + "Take one down and pass it around, 53 bottles of beer on the wall.\n" + + "\n" + + "53 bottles of beer on the wall, 53 bottles of beer.\n" + + "Take one down and pass it around, 52 bottles of beer on the wall.\n" + + "\n" + + "52 bottles of beer on the wall, 52 bottles of beer.\n" + + "Take one down and pass it around, 51 bottles of beer on the wall.\n" + + "\n" + + "51 bottles of beer on the wall, 51 bottles of beer.\n" + + "Take one down and pass it around, 50 bottles of beer on the wall.\n" + + "\n" + + "50 bottles of beer on the wall, 50 bottles of beer.\n" + + "Take one down and pass it around, 49 bottles of beer on the wall.\n" + + "\n" + + "49 bottles of beer on the wall, 49 bottles of beer.\n" + + "Take one down and pass it around, 48 bottles of beer on the wall.\n" + + "\n" + + "48 bottles of beer on the wall, 48 bottles of beer.\n" + + "Take one down and pass it around, 47 bottles of beer on the wall.\n" + + "\n" + + "47 bottles of beer on the wall, 47 bottles of beer.\n" + + "Take one down and pass it around, 46 bottles of beer on the wall.\n" + + "\n" + + "46 bottles of beer on the wall, 46 bottles of beer.\n" + + "Take one down and pass it around, 45 bottles of beer on the wall.\n" + + "\n" + + "45 bottles of beer on the wall, 45 bottles of beer.\n" + + "Take one down and pass it around, 44 bottles of beer on the wall.\n" + + "\n" + + "44 bottles of beer on the wall, 44 bottles of beer.\n" + + "Take one down and pass it around, 43 bottles of beer on the wall.\n" + + "\n" + + "43 bottles of beer on the wall, 43 bottles of beer.\n" + + "Take one down and pass it around, 42 bottles of beer on the wall.\n" + + "\n" + + "42 bottles of beer on the wall, 42 bottles of beer.\n" + + "Take one down and pass it around, 41 bottles of beer on the wall.\n" + + "\n" + + "41 bottles of beer on the wall, 41 bottles of beer.\n" + + "Take one down and pass it around, 40 bottles of beer on the wall.\n" + + "\n" + + "40 bottles of beer on the wall, 40 bottles of beer.\n" + + "Take one down and pass it around, 39 bottles of beer on the wall.\n" + + "\n" + + "39 bottles of beer on the wall, 39 bottles of beer.\n" + + "Take one down and pass it around, 38 bottles of beer on the wall.\n" + + "\n" + + "38 bottles of beer on the wall, 38 bottles of beer.\n" + + "Take one down and pass it around, 37 bottles of beer on the wall.\n" + + "\n" + + "37 bottles of beer on the wall, 37 bottles of beer.\n" + + "Take one down and pass it around, 36 bottles of beer on the wall.\n" + + "\n" + + "36 bottles of beer on the wall, 36 bottles of beer.\n" + + "Take one down and pass it around, 35 bottles of beer on the wall.\n" + + "\n" + + "35 bottles of beer on the wall, 35 bottles of beer.\n" + + "Take one down and pass it around, 34 bottles of beer on the wall.\n" + + "\n" + + "34 bottles of beer on the wall, 34 bottles of beer.\n" + + "Take one down and pass it around, 33 bottles of beer on the wall.\n" + + "\n" + + "33 bottles of beer on the wall, 33 bottles of beer.\n" + + "Take one down and pass it around, 32 bottles of beer on the wall.\n" + + "\n" + + "32 bottles of beer on the wall, 32 bottles of beer.\n" + + "Take one down and pass it around, 31 bottles of beer on the wall.\n" + + "\n" + + "31 bottles of beer on the wall, 31 bottles of beer.\n" + + "Take one down and pass it around, 30 bottles of beer on the wall.\n" + + "\n" + + "30 bottles of beer on the wall, 30 bottles of beer.\n" + + "Take one down and pass it around, 29 bottles of beer on the wall.\n" + + "\n" + + "29 bottles of beer on the wall, 29 bottles of beer.\n" + + "Take one down and pass it around, 28 bottles of beer on the wall.\n" + + "\n" + + "28 bottles of beer on the wall, 28 bottles of beer.\n" + + "Take one down and pass it around, 27 bottles of beer on the wall.\n" + + "\n" + + "27 bottles of beer on the wall, 27 bottles of beer.\n" + + "Take one down and pass it around, 26 bottles of beer on the wall.\n" + + "\n" + + "26 bottles of beer on the wall, 26 bottles of beer.\n" + + "Take one down and pass it around, 25 bottles of beer on the wall.\n" + + "\n" + + "25 bottles of beer on the wall, 25 bottles of beer.\n" + + "Take one down and pass it around, 24 bottles of beer on the wall.\n" + + "\n" + + "24 bottles of beer on the wall, 24 bottles of beer.\n" + + "Take one down and pass it around, 23 bottles of beer on the wall.\n" + + "\n" + + "23 bottles of beer on the wall, 23 bottles of beer.\n" + + "Take one down and pass it around, 22 bottles of beer on the wall.\n" + + "\n" + + "22 bottles of beer on the wall, 22 bottles of beer.\n" + + "Take one down and pass it around, 21 bottles of beer on the wall.\n" + + "\n" + + "21 bottles of beer on the wall, 21 bottles of beer.\n" + + "Take one down and pass it around, 20 bottles of beer on the wall.\n" + + "\n" + + "20 bottles of beer on the wall, 20 bottles of beer.\n" + + "Take one down and pass it around, 19 bottles of beer on the wall.\n" + + "\n" + + "19 bottles of beer on the wall, 19 bottles of beer.\n" + + "Take one down and pass it around, 18 bottles of beer on the wall.\n" + + "\n" + + "18 bottles of beer on the wall, 18 bottles of beer.\n" + + "Take one down and pass it around, 17 bottles of beer on the wall.\n" + + "\n" + + "17 bottles of beer on the wall, 17 bottles of beer.\n" + + "Take one down and pass it around, 16 bottles of beer on the wall.\n" + + "\n" + + "16 bottles of beer on the wall, 16 bottles of beer.\n" + + "Take one down and pass it around, 15 bottles of beer on the wall.\n" + + "\n" + + "15 bottles of beer on the wall, 15 bottles of beer.\n" + + "Take one down and pass it around, 14 bottles of beer on the wall.\n" + + "\n" + + "14 bottles of beer on the wall, 14 bottles of beer.\n" + + "Take one down and pass it around, 13 bottles of beer on the wall.\n" + + "\n" + + "13 bottles of beer on the wall, 13 bottles of beer.\n" + + "Take one down and pass it around, 12 bottles of beer on the wall.\n" + + "\n" + + "12 bottles of beer on the wall, 12 bottles of beer.\n" + + "Take one down and pass it around, 11 bottles of beer on the wall.\n" + + "\n" + + "11 bottles of beer on the wall, 11 bottles of beer.\n" + + "Take one down and pass it around, 10 bottles of beer on the wall.\n" + + "\n" + + "10 bottles of beer on the wall, 10 bottles of beer.\n" + + "Take one down and pass it around, 9 bottles of beer on the wall.\n" + + "\n" + + "9 bottles of beer on the wall, 9 bottles of beer.\n" + + "Take one down and pass it around, 8 bottles of beer on the wall.\n" + + "\n" + + "8 bottles of beer on the wall, 8 bottles of beer.\n" + + "Take one down and pass it around, 7 bottles of beer on the wall.\n" + + "\n" + + "7 bottles of beer on the wall, 7 bottles of beer.\n" + + "Take one down and pass it around, 6 bottles of beer on the wall.\n" + + "\n" + + "6 bottles of beer on the wall, 6 bottles of beer.\n" + + "Take one down and pass it around, 5 bottles of beer on the wall.\n" + + "\n" + + "5 bottles of beer on the wall, 5 bottles of beer.\n" + + "Take one down and pass it around, 4 bottles of beer on the wall.\n" + + "\n" + + "4 bottles of beer on the wall, 4 bottles of beer.\n" + + "Take one down and pass it around, 3 bottles of beer on the wall.\n" + + "\n" + + "3 bottles of beer on the wall, 3 bottles of beer.\n" + + "Take one down and pass it around, 2 bottles of beer on the wall.\n" + + "\n" + + "2 bottles of beer on the wall, 2 bottles of beer.\n" + + "Take one down and pass it around, 1 bottle of beer on the wall.\n" + + "\n" + + "1 bottle of beer on the wall, 1 bottle of beer.\n" + + "Take it down and pass it around, no more bottles of beer on the wall.\n" + + "\n" + + "No more bottles of beer on the wall, no more bottles of beer.\n" + + "Go to the store and buy some more, 99 bottles of beer on the wall.\n" + ""; Assert.Equal(expected, BeerSong.Verses(99, 0)); } diff --git a/exercises/bob/BobTest.cs b/exercises/bob/BobTest.cs index 12d2997ddb..33d609e019 100644 --- a/exercises/bob/BobTest.cs +++ b/exercises/bob/BobTest.cs @@ -1,3 +1,5 @@ +// This file was auto-generated based on version 1.0.0 of the canonical data. + using Xunit; public class BobTest diff --git a/exercises/food-chain/FoodChainTest.cs b/exercises/food-chain/FoodChainTest.cs index 91ae55af8c..51ffbbf297 100644 --- a/exercises/food-chain/FoodChainTest.cs +++ b/exercises/food-chain/FoodChainTest.cs @@ -8,7 +8,7 @@ public class FoodChainTest public void Fly() { var expected = - "I know an old lady who swallowed a fly.\n"+ + "I know an old lady who swallowed a fly.\n" + "I don't know why she swallowed the fly. Perhaps she'll die."; Assert.Equal(expected, FoodChain.Verse(1)); } @@ -17,9 +17,9 @@ public void Fly() public void Spider() { var expected = - "I know an old lady who swallowed a spider.\n"+ - "It wriggled and jiggled and tickled inside her.\n"+ - "She swallowed the spider to catch the fly.\n"+ + "I know an old lady who swallowed a spider.\n" + + "It wriggled and jiggled and tickled inside her.\n" + + "She swallowed the spider to catch the fly.\n" + "I don't know why she swallowed the fly. Perhaps she'll die."; Assert.Equal(expected, FoodChain.Verse(2)); } @@ -28,10 +28,10 @@ public void Spider() public void Bird() { var expected = - "I know an old lady who swallowed a bird.\n"+ - "How absurd to swallow a bird!\n"+ - "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.\n"+ - "She swallowed the spider to catch the fly.\n"+ + "I know an old lady who swallowed a bird.\n" + + "How absurd to swallow a bird!\n" + + "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.\n" + + "She swallowed the spider to catch the fly.\n" + "I don't know why she swallowed the fly. Perhaps she'll die."; Assert.Equal(expected, FoodChain.Verse(3)); } @@ -40,11 +40,11 @@ public void Bird() public void Cat() { var expected = - "I know an old lady who swallowed a cat.\n"+ - "Imagine that, to swallow a cat!\n"+ - "She swallowed the cat to catch the bird.\n"+ - "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.\n"+ - "She swallowed the spider to catch the fly.\n"+ + "I know an old lady who swallowed a cat.\n" + + "Imagine that, to swallow a cat!\n" + + "She swallowed the cat to catch the bird.\n" + + "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.\n" + + "She swallowed the spider to catch the fly.\n" + "I don't know why she swallowed the fly. Perhaps she'll die."; Assert.Equal(expected, FoodChain.Verse(4)); } @@ -53,12 +53,12 @@ public void Cat() public void Dog() { var expected = - "I know an old lady who swallowed a dog.\n"+ - "What a hog, to swallow a dog!\n"+ - "She swallowed the dog to catch the cat.\n"+ - "She swallowed the cat to catch the bird.\n"+ - "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.\n"+ - "She swallowed the spider to catch the fly.\n"+ + "I know an old lady who swallowed a dog.\n" + + "What a hog, to swallow a dog!\n" + + "She swallowed the dog to catch the cat.\n" + + "She swallowed the cat to catch the bird.\n" + + "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.\n" + + "She swallowed the spider to catch the fly.\n" + "I don't know why she swallowed the fly. Perhaps she'll die."; Assert.Equal(expected, FoodChain.Verse(5)); } @@ -67,13 +67,13 @@ public void Dog() public void Goat() { var expected = - "I know an old lady who swallowed a goat.\n"+ - "Just opened her throat and swallowed a goat!\n"+ - "She swallowed the goat to catch the dog.\n"+ - "She swallowed the dog to catch the cat.\n"+ - "She swallowed the cat to catch the bird.\n"+ - "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.\n"+ - "She swallowed the spider to catch the fly.\n"+ + "I know an old lady who swallowed a goat.\n" + + "Just opened her throat and swallowed a goat!\n" + + "She swallowed the goat to catch the dog.\n" + + "She swallowed the dog to catch the cat.\n" + + "She swallowed the cat to catch the bird.\n" + + "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.\n" + + "She swallowed the spider to catch the fly.\n" + "I don't know why she swallowed the fly. Perhaps she'll die."; Assert.Equal(expected, FoodChain.Verse(6)); } @@ -82,14 +82,14 @@ public void Goat() public void Cow() { var expected = - "I know an old lady who swallowed a cow.\n"+ - "I don't know how she swallowed a cow!\n"+ - "She swallowed the cow to catch the goat.\n"+ - "She swallowed the goat to catch the dog.\n"+ - "She swallowed the dog to catch the cat.\n"+ - "She swallowed the cat to catch the bird.\n"+ - "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.\n"+ - "She swallowed the spider to catch the fly.\n"+ + "I know an old lady who swallowed a cow.\n" + + "I don't know how she swallowed a cow!\n" + + "She swallowed the cow to catch the goat.\n" + + "She swallowed the goat to catch the dog.\n" + + "She swallowed the dog to catch the cat.\n" + + "She swallowed the cat to catch the bird.\n" + + "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.\n" + + "She swallowed the spider to catch the fly.\n" + "I don't know why she swallowed the fly. Perhaps she'll die."; Assert.Equal(expected, FoodChain.Verse(7)); } @@ -98,7 +98,7 @@ public void Cow() public void Horse() { var expected = - "I know an old lady who swallowed a horse.\n"+ + "I know an old lady who swallowed a horse.\n" + "She's dead, of course!"; Assert.Equal(expected, FoodChain.Verse(8)); } @@ -107,18 +107,18 @@ public void Horse() public void Multiple_verses() { var expected = - "I know an old lady who swallowed a fly.\n"+ - "I don't know why she swallowed the fly. Perhaps she'll die.\n"+ - "\n"+ - "I know an old lady who swallowed a spider.\n"+ - "It wriggled and jiggled and tickled inside her.\n"+ - "She swallowed the spider to catch the fly.\n"+ - "I don't know why she swallowed the fly. Perhaps she'll die.\n"+ - "\n"+ - "I know an old lady who swallowed a bird.\n"+ - "How absurd to swallow a bird!\n"+ - "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.\n"+ - "She swallowed the spider to catch the fly.\n"+ + "I know an old lady who swallowed a fly.\n" + + "I don't know why she swallowed the fly. Perhaps she'll die.\n" + + "\n" + + "I know an old lady who swallowed a spider.\n" + + "It wriggled and jiggled and tickled inside her.\n" + + "She swallowed the spider to catch the fly.\n" + + "I don't know why she swallowed the fly. Perhaps she'll die.\n" + + "\n" + + "I know an old lady who swallowed a bird.\n" + + "How absurd to swallow a bird!\n" + + "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.\n" + + "She swallowed the spider to catch the fly.\n" + "I don't know why she swallowed the fly. Perhaps she'll die."; Assert.Equal(expected, FoodChain.Verse(1, 3)); } @@ -127,55 +127,55 @@ public void Multiple_verses() public void Full_song() { var expected = - "I know an old lady who swallowed a fly.\n"+ - "I don't know why she swallowed the fly. Perhaps she'll die.\n"+ - "\n"+ - "I know an old lady who swallowed a spider.\n"+ - "It wriggled and jiggled and tickled inside her.\n"+ - "She swallowed the spider to catch the fly.\n"+ - "I don't know why she swallowed the fly. Perhaps she'll die.\n"+ - "\n"+ - "I know an old lady who swallowed a bird.\n"+ - "How absurd to swallow a bird!\n"+ - "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.\n"+ - "She swallowed the spider to catch the fly.\n"+ - "I don't know why she swallowed the fly. Perhaps she'll die.\n"+ - "\n"+ - "I know an old lady who swallowed a cat.\n"+ - "Imagine that, to swallow a cat!\n"+ - "She swallowed the cat to catch the bird.\n"+ - "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.\n"+ - "She swallowed the spider to catch the fly.\n"+ - "I don't know why she swallowed the fly. Perhaps she'll die.\n"+ - "\n"+ - "I know an old lady who swallowed a dog.\n"+ - "What a hog, to swallow a dog!\n"+ - "She swallowed the dog to catch the cat.\n"+ - "She swallowed the cat to catch the bird.\n"+ - "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.\n"+ - "She swallowed the spider to catch the fly.\n"+ - "I don't know why she swallowed the fly. Perhaps she'll die.\n"+ - "\n"+ - "I know an old lady who swallowed a goat.\n"+ - "Just opened her throat and swallowed a goat!\n"+ - "She swallowed the goat to catch the dog.\n"+ - "She swallowed the dog to catch the cat.\n"+ - "She swallowed the cat to catch the bird.\n"+ - "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.\n"+ - "She swallowed the spider to catch the fly.\n"+ - "I don't know why she swallowed the fly. Perhaps she'll die.\n"+ - "\n"+ - "I know an old lady who swallowed a cow.\n"+ - "I don't know how she swallowed a cow!\n"+ - "She swallowed the cow to catch the goat.\n"+ - "She swallowed the goat to catch the dog.\n"+ - "She swallowed the dog to catch the cat.\n"+ - "She swallowed the cat to catch the bird.\n"+ - "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.\n"+ - "She swallowed the spider to catch the fly.\n"+ - "I don't know why she swallowed the fly. Perhaps she'll die.\n"+ - "\n"+ - "I know an old lady who swallowed a horse.\n"+ + "I know an old lady who swallowed a fly.\n" + + "I don't know why she swallowed the fly. Perhaps she'll die.\n" + + "\n" + + "I know an old lady who swallowed a spider.\n" + + "It wriggled and jiggled and tickled inside her.\n" + + "She swallowed the spider to catch the fly.\n" + + "I don't know why she swallowed the fly. Perhaps she'll die.\n" + + "\n" + + "I know an old lady who swallowed a bird.\n" + + "How absurd to swallow a bird!\n" + + "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.\n" + + "She swallowed the spider to catch the fly.\n" + + "I don't know why she swallowed the fly. Perhaps she'll die.\n" + + "\n" + + "I know an old lady who swallowed a cat.\n" + + "Imagine that, to swallow a cat!\n" + + "She swallowed the cat to catch the bird.\n" + + "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.\n" + + "She swallowed the spider to catch the fly.\n" + + "I don't know why she swallowed the fly. Perhaps she'll die.\n" + + "\n" + + "I know an old lady who swallowed a dog.\n" + + "What a hog, to swallow a dog!\n" + + "She swallowed the dog to catch the cat.\n" + + "She swallowed the cat to catch the bird.\n" + + "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.\n" + + "She swallowed the spider to catch the fly.\n" + + "I don't know why she swallowed the fly. Perhaps she'll die.\n" + + "\n" + + "I know an old lady who swallowed a goat.\n" + + "Just opened her throat and swallowed a goat!\n" + + "She swallowed the goat to catch the dog.\n" + + "She swallowed the dog to catch the cat.\n" + + "She swallowed the cat to catch the bird.\n" + + "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.\n" + + "She swallowed the spider to catch the fly.\n" + + "I don't know why she swallowed the fly. Perhaps she'll die.\n" + + "\n" + + "I know an old lady who swallowed a cow.\n" + + "I don't know how she swallowed a cow!\n" + + "She swallowed the cow to catch the goat.\n" + + "She swallowed the goat to catch the dog.\n" + + "She swallowed the dog to catch the cat.\n" + + "She swallowed the cat to catch the bird.\n" + + "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.\n" + + "She swallowed the spider to catch the fly.\n" + + "I don't know why she swallowed the fly. Perhaps she'll die.\n" + + "\n" + + "I know an old lady who swallowed a horse.\n" + "She's dead, of course!"; Assert.Equal(expected, FoodChain.Verse(1, 8)); } diff --git a/exercises/nth-prime/NthPrimeTest.cs b/exercises/nth-prime/NthPrimeTest.cs index 0ed1699694..74885010b7 100644 --- a/exercises/nth-prime/NthPrimeTest.cs +++ b/exercises/nth-prime/NthPrimeTest.cs @@ -1,7 +1,6 @@ // This file was auto-generated based on version 1.0.0 of the canonical data. using Xunit; -using System; public class NthPrimeTest { @@ -32,6 +31,6 @@ public void Big_prime() [Fact(Skip = "Remove to run test")] public void There_is_no_zeroth_prime() { - Assert.Throws(() => NthPrime.Prime(0)); + Assert.Throws(() => NthPrime.Prime(0)); } } \ No newline at end of file diff --git a/exercises/perfect-numbers/PerfectNumbersTest.cs b/exercises/perfect-numbers/PerfectNumbersTest.cs index 01b2a9e6df..3f380e8c20 100644 --- a/exercises/perfect-numbers/PerfectNumbersTest.cs +++ b/exercises/perfect-numbers/PerfectNumbersTest.cs @@ -1,7 +1,6 @@ // This file was auto-generated based on version 1.0.1 of the canonical data. using Xunit; -using System; public class PerfectNumbersTest { @@ -74,12 +73,12 @@ public void Edge_case_no_factors_other_than_itself_is_classified_correctly() [Fact(Skip = "Remove to run test")] public void Zero_is_rejected_not_a_natural_number_() { - Assert.Throws(() => PerfectNumbers.Classify(0)); + Assert.Throws(() => PerfectNumbers.Classify(0)); } [Fact(Skip = "Remove to run test")] public void Negative_integer_is_rejected_not_a_natural_number_() { - Assert.Throws(() => PerfectNumbers.Classify(-1)); + Assert.Throws(() => PerfectNumbers.Classify(-1)); } } \ No newline at end of file diff --git a/exercises/wordy/WordyTest.cs b/exercises/wordy/WordyTest.cs index 2b76cab6cf..a96a5709c4 100644 --- a/exercises/wordy/WordyTest.cs +++ b/exercises/wordy/WordyTest.cs @@ -1,7 +1,6 @@ // This file was auto-generated based on version 1.0.0 of the canonical data. using Xunit; -using System; public class WordyTest { @@ -92,12 +91,12 @@ public void Multiple_division() [Fact(Skip = "Remove to run test")] public void Unknown_operation() { - Assert.Throws(() => Wordy.Answer("What is 52 cubed?")); + Assert.Throws(() => Wordy.Answer("What is 52 cubed?")); } [Fact(Skip = "Remove to run test")] public void Non_math_question() { - Assert.Throws(() => Wordy.Answer("Who is the President of the United States?")); + Assert.Throws(() => Wordy.Answer("Who is the President of the United States?")); } } \ No newline at end of file diff --git a/generators/Classes/TestClass.cs b/generators/Classes/TestClass.cs deleted file mode 100644 index 4be84ca6ca..0000000000 --- a/generators/Classes/TestClass.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Collections.Generic; -using Generators.Methods; - -namespace Generators.Classes -{ - public class TestClass - { - public ISet UsingNamespaces { get; set; } = new HashSet { "Xunit" }; - public string ClassName { get; set; } - public string BeforeTestMethods { get; set; } - public TestMethod[] TestMethods { get; set; } - public string AfterTestMethods { get; set; } - public string CanonicalDataVersion { get; set; } - } -} \ No newline at end of file diff --git a/generators/Classes/TestClassNameTransformer.cs b/generators/Classes/TestClassNameTransformer.cs deleted file mode 100644 index d6f69e61b4..0000000000 --- a/generators/Classes/TestClassNameTransformer.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Humanizer; - -namespace Generators.Classes -{ - public class TestClassNameTransformer : IStringTransformer - { - public string Transform(string input) => $"{input.Dehumanize()}Test"; - } -} \ No newline at end of file diff --git a/generators/Classes/TestClassRenderer.cs b/generators/Classes/TestClassRenderer.cs deleted file mode 100644 index 6ab7446e91..0000000000 --- a/generators/Classes/TestClassRenderer.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Generators.Methods; - -namespace Generators.Classes -{ - public static class TestClassRenderer - { - private const string TestClassTemplate = -@"// This file was auto-generated based on version {CanonicalDataVersion} of the canonical data. - -{UsingNamespaces} - -public class {ClassName} -{ -{Body} -}"; - - public static string Render(TestClass testClass) => - TestClassTemplate - .Replace("{CanonicalDataVersion}", testClass.CanonicalDataVersion) - .Replace("{UsingNamespaces}", RenderUsingNamespaces(testClass)) - .Replace("{ClassName}", testClass.ClassName) - .Replace("{Body}", RenderBody(testClass)); - - private static string RenderUsingNamespaces(TestClass testClass) => - string.Join("\n", testClass.UsingNamespaces.Select(usingNamespace => $"using {usingNamespace};")); - - private static string RenderBody(TestClass testClass) => - string.Join("\n\n", GetBodyParts(testClass)); - - private static IEnumerable GetBodyParts(TestClass testClass) => - from bodyPart in new [] { testClass.BeforeTestMethods, RenderTestMethods(testClass), testClass.AfterTestMethods } - where !string.IsNullOrWhiteSpace(bodyPart) - select bodyPart; - - private static string RenderTestMethods(TestClass testClass) => - string.Join("\n\n", testClass.TestMethods.Select(TestMethodRenderer.Render)); - } -} diff --git a/generators/Classes/TestedClassNameTransformer.cs b/generators/Classes/TestedClassNameTransformer.cs deleted file mode 100644 index 3d12c3a30e..0000000000 --- a/generators/Classes/TestedClassNameTransformer.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Humanizer; - -namespace Generators.Classes -{ - public class TestedClassNameTransformer : IStringTransformer - { - public string Transform(string input) => input.Dehumanize(); - } -} \ No newline at end of file diff --git a/generators/Data/CanonicalDataCaseJsonConverter.cs b/generators/Data/CanonicalDataCaseJsonConverter.cs deleted file mode 100644 index c1003e25e8..0000000000 --- a/generators/Data/CanonicalDataCaseJsonConverter.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Collections.Generic; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace Generators.Data -{ - public class CanonicalDataCaseJsonConverter : JsonConverter - { - public override bool CanConvert(Type objectType) - { - return typeof(CanonicalDataCase) == objectType; - } - - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - var jToken = JToken.ReadFrom(reader); - - var canonicalDataCase = new CanonicalDataCase(); - serializer.Populate(new JTokenReader(jToken), canonicalDataCase); - - canonicalDataCase.Data = jToken.ToObject>(); - - return canonicalDataCase; - } - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - throw new NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/generators/Data/CanonicalDataValue.cs b/generators/Data/CanonicalDataValue.cs deleted file mode 100644 index fa04423b55..0000000000 --- a/generators/Data/CanonicalDataValue.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; -using Newtonsoft.Json.Linq; - -namespace Generators.Data -{ - public static class CanonicalDataValue - { - public static string ExpectedToMultiLineString(object expected) - { - switch (expected) - { - case IEnumerable enumerable: - return string.Join("\\n\"+\n\"", enumerable); - case JArray jarray: - return ExpectedToMultiLineString(((JArray) expected).Values()); - case string str: - return ExpectedToMultiLineString(str.Split('\n')); - default: - throw new ArgumentException("Cannot convert expected value to multil-ine string."); - } - } - } -} diff --git a/generators/Exercise.cs b/generators/Exercise.cs new file mode 100644 index 0000000000..48d254ad05 --- /dev/null +++ b/generators/Exercise.cs @@ -0,0 +1,26 @@ +using Generators.Input; +using Generators.Output; +using Humanizer; + +namespace Generators +{ + public abstract class Exercise + { + protected Exercise() + { + Name = GetType().Name.Kebaberize(); + CanonicalData = CanonicalDataParser.Parse(Name); + Configuration = new ExerciseConfiguration(); + } + + public string Name { get; } + public CanonicalData CanonicalData { get; } + public ExerciseConfiguration Configuration { get; } + + public void Generate() => TestClassFile.Write(this, Render()); + + protected virtual string Render() => TestClassRenderer.Render(CreateTestClass()); + + protected virtual TestClass CreateTestClass() => TestClassGenerator.Create(this); + } +} \ No newline at end of file diff --git a/generators/ExerciseConfiguration.cs b/generators/ExerciseConfiguration.cs new file mode 100644 index 0000000000..4d280556ab --- /dev/null +++ b/generators/ExerciseConfiguration.cs @@ -0,0 +1,12 @@ +using System; +using Newtonsoft.Json.Linq; + +namespace Generators +{ + public class ExerciseConfiguration + { + public TestedMethodType TestedMethodType { get; set; } = TestedMethodType.Static; + public Type ExceptionType { get; set; } = typeof(ArgumentException); + public Func ThrowExceptionWhenExpectedValueEquals { get; set; } = x => x is JObject; + } +} \ No newline at end of file diff --git a/generators/Exercises/Acronym.cs b/generators/Exercises/Acronym.cs new file mode 100644 index 0000000000..6a8b12c4f9 --- /dev/null +++ b/generators/Exercises/Acronym.cs @@ -0,0 +1,6 @@ +namespace Generators.Exercises +{ + public class Acronym : Exercise + { + } +} \ No newline at end of file diff --git a/generators/Exercises/AcronymExercise.cs b/generators/Exercises/AcronymExercise.cs deleted file mode 100644 index d7a6654022..0000000000 --- a/generators/Exercises/AcronymExercise.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Generators.Data; -using Generators.Methods; - -namespace Generators.Exercises -{ - public class AcronymExercise : EqualityExercise - { - public AcronymExercise() : base("acronym") - { - } - - protected override TestMethodData CreateTestMethodData(CanonicalData canonicalData, CanonicalDataCase canonicalDataCase, int index) - { - var testMethodData = base.CreateTestMethodData(canonicalData, canonicalDataCase, index); - testMethodData.Options.InputProperty = "phrase"; - - return testMethodData; - } - } -} \ No newline at end of file diff --git a/generators/Exercises/AtbashCipher.cs b/generators/Exercises/AtbashCipher.cs new file mode 100644 index 0000000000..b1f8eca832 --- /dev/null +++ b/generators/Exercises/AtbashCipher.cs @@ -0,0 +1,6 @@ +namespace Generators.Exercises +{ + public class AtbashCipher : Exercise + { + } +} \ No newline at end of file diff --git a/generators/Exercises/AtbashCipherExercise.cs b/generators/Exercises/AtbashCipherExercise.cs deleted file mode 100644 index c4489ec6a2..0000000000 --- a/generators/Exercises/AtbashCipherExercise.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Generators.Data; -using Generators.Methods; - -namespace Generators.Exercises -{ - public class AtbashCipherExercise : EqualityExercise - { - public AtbashCipherExercise() : base("atbash-cipher") - { - } - - protected override TestMethodOptions CreateTestMethodOptions(CanonicalData canonicalData, CanonicalDataCase canonicalDataCase, int index) - { - var testMethodOptions = base.CreateTestMethodOptions(canonicalData, canonicalDataCase, index); - testMethodOptions.InputProperty = "phrase"; - - return testMethodOptions; - } - } -} \ No newline at end of file diff --git a/generators/Exercises/BeerSong.cs b/generators/Exercises/BeerSong.cs new file mode 100644 index 0000000000..0ece079243 --- /dev/null +++ b/generators/Exercises/BeerSong.cs @@ -0,0 +1,13 @@ +using Generators.Output; + +namespace Generators.Exercises +{ + public class BeerSong : Exercise + { + public BeerSong() + { + foreach (var canonicalDataCase in CanonicalData.Cases) + canonicalDataCase.Expected = new MultiLineString(canonicalDataCase.Expected.ToString()); + } + } +} \ No newline at end of file diff --git a/generators/Exercises/BeerSongExercise.cs b/generators/Exercises/BeerSongExercise.cs deleted file mode 100644 index 2d8e3a8b61..0000000000 --- a/generators/Exercises/BeerSongExercise.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Generators.Data; -using Generators.Methods; - -namespace Generators.Exercises -{ - public class BeerSongExercise : EqualityExercise - { - public BeerSongExercise() : base("beer-song") - { - } - - protected override TestMethodData CreateTestMethodData(CanonicalData canonicalData, CanonicalDataCase canonicalDataCase, int index) - { - var testMethodData = base.CreateTestMethodData(canonicalData, canonicalDataCase, index); - - testMethodData.Options.UseVariableForExpected = true; - testMethodData.Options.FormatExpected = true; - - testMethodData.CanonicalDataCase.Expected = CanonicalDataValue.ExpectedToMultiLineString(testMethodData.CanonicalDataCase.Expected); - - if (testMethodData.CanonicalDataCase.Property == "verse") - testMethodData.Options.InputProperty = "number"; - else - testMethodData.CanonicalDataCase.Input = new[] - { - testMethodData.CanonicalDataCase.Data["beginning"], - testMethodData.CanonicalDataCase.Data["end"] - }; - - return testMethodData; - } - } -} \ No newline at end of file diff --git a/generators/Exercises/Bob.cs b/generators/Exercises/Bob.cs index 81441ed2e3..14c27bf0d9 100644 --- a/generators/Exercises/Bob.cs +++ b/generators/Exercises/Bob.cs @@ -1,20 +1,6 @@ -using Generators.Data; -using Generators.Methods; - -namespace Generators.Exercises +namespace Generators.Exercises { - public class BobExercise : EqualityExercise + public class Bob : Exercise { - public BobExercise() : base("bob") - { - } - - protected override TestMethodData CreateTestMethodData(CanonicalData canonicalData, CanonicalDataCase canonicalDataCase, int index) - { - var testMethodData = base.CreateTestMethodData(canonicalData, canonicalDataCase, index); - testMethodData.Options.InputProperty = "input"; - - return testMethodData; - } } } \ No newline at end of file diff --git a/generators/Exercises/BooleanExercise.cs b/generators/Exercises/BooleanExercise.cs deleted file mode 100644 index afc9d87d71..0000000000 --- a/generators/Exercises/BooleanExercise.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Generators.Methods; - -namespace Generators.Exercises -{ - public abstract class BooleanExercise : Exercise - { - protected BooleanExercise(string name) : base(name) - { - } - - protected override TestMethod CreateTestMethod(TestMethodData testMethodData) - => CreateBooleanTestMethod(testMethodData); - } -} \ No newline at end of file diff --git a/generators/Exercises/EqualityExercise.cs b/generators/Exercises/EqualityExercise.cs deleted file mode 100644 index fc729a7967..0000000000 --- a/generators/Exercises/EqualityExercise.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Generators.Methods; - -namespace Generators.Exercises -{ - public abstract class EqualityExercise : Exercise - { - protected EqualityExercise(string name) : base(name) - { - } - - protected override TestMethod CreateTestMethod(TestMethodData testMethodData) - { - if (testMethodData.Options.ThrowExceptionWhenExpectedValueEquals(testMethodData.CanonicalDataCase.Expected)) - return CreateExceptionTestMethod(testMethodData); - - return CreateEqualityTestMethod(testMethodData); - } - } -} \ No newline at end of file diff --git a/generators/Exercises/Exercise.cs b/generators/Exercises/Exercise.cs deleted file mode 100644 index 00907a2a12..0000000000 --- a/generators/Exercises/Exercise.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Generators.Classes; -using Generators.Data; -using Generators.Methods; -using Humanizer; -using Newtonsoft.Json.Linq; -using To = Generators.Helpers.To; - -namespace Generators.Exercises -{ - public abstract class Exercise - { - private static readonly BooleanTestMethodGenerator BooleanTestMethodGenerator = new BooleanTestMethodGenerator(); - private static readonly EqualityTestMethodGenerator EqualityTestMethodGenerator = new EqualityTestMethodGenerator(); - private static readonly ExceptionTestMethodGenerator ExceptionTestMethodGenerator = new ExceptionTestMethodGenerator(); - - protected Exercise(string name) - { - Name = name; - } - - public string Name { get; } - - public TestClass CreateTestClass(CanonicalData canonicalData) - { - var testClass = new TestClass - { - ClassName = Name.Transform(To.TestClassName), - TestMethods = CreateTestMethods(canonicalData).ToArray(), - CanonicalDataVersion = canonicalData.Version - }; - - AddTestMethodUsingNamespaces(testClass); - - return testClass; - } - - private static void AddTestMethodUsingNamespaces(TestClass testClass) - { - foreach (var testMethod in testClass.TestMethods) - testClass.UsingNamespaces.UnionWith(testMethod.UsingNamespaces); - } - - protected abstract TestMethod CreateTestMethod(TestMethodData testMethodData); - - protected virtual IEnumerable CreateTestMethods(CanonicalData canonicalData) - => canonicalData.Cases.Select((t, i) => CreateTestMethod(canonicalData, t, i)); - - protected virtual TestMethod CreateTestMethod(CanonicalData canonicalData, CanonicalDataCase canonicalDataCase, int index) - { - var testMethodData = CreateTestMethodData(canonicalData, canonicalDataCase, index); - - if (testMethodData.CanonicalDataCase.Expected is JObject jObject) - return CreateExceptionTestMethod(testMethodData); - - return CreateTestMethod(testMethodData); - } - - protected virtual TestMethodData CreateTestMethodData(CanonicalData canonicalData, CanonicalDataCase canonicalDataCase, int index) - => new TestMethodData - { - CanonicalData = canonicalData, - CanonicalDataCase = canonicalDataCase, - Index = index, - Options = CreateTestMethodOptions(canonicalData, canonicalDataCase, index) - }; - - protected virtual TestMethodOptions CreateTestMethodOptions(CanonicalData canonicalData, CanonicalDataCase canonicalDataCase, int index) - => new TestMethodOptions(); - - protected virtual TestMethod CreateBooleanTestMethod(TestMethodData testMethodData) - => BooleanTestMethodGenerator.Create(testMethodData); - - protected virtual TestMethod CreateEqualityTestMethod(TestMethodData testMethodData) - => EqualityTestMethodGenerator.Create(testMethodData); - - protected virtual TestMethod CreateExceptionTestMethod(TestMethodData testMethodData) - => ExceptionTestMethodGenerator.Create(testMethodData); - } -} \ No newline at end of file diff --git a/generators/Exercises/FoodChain.cs b/generators/Exercises/FoodChain.cs new file mode 100644 index 0000000000..fb4ed432da --- /dev/null +++ b/generators/Exercises/FoodChain.cs @@ -0,0 +1,14 @@ +using Generators.Output; +using Newtonsoft.Json.Linq; + +namespace Generators.Exercises +{ + public class FoodChain : Exercise + { + public FoodChain() + { + foreach (var canonicalDataCase in CanonicalData.Cases) + canonicalDataCase.Expected = new MultiLineString(((JArray)canonicalDataCase.Expected).Values()); + } + } +} \ No newline at end of file diff --git a/generators/Exercises/FoodChainExercise.cs b/generators/Exercises/FoodChainExercise.cs deleted file mode 100644 index 0e3e1800cd..0000000000 --- a/generators/Exercises/FoodChainExercise.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Generators.Data; -using Generators.Methods; - -namespace Generators.Exercises -{ - public class FoodChainExercise : EqualityExercise - { - public FoodChainExercise() : base("food-chain") - { - } - - protected override TestMethodData CreateTestMethodData(CanonicalData canonicalData, CanonicalDataCase canonicalDataCase, int index) - { - var testMethodData = base.CreateTestMethodData(canonicalData, canonicalDataCase, index); - - testMethodData.Options.UseVariableForExpected = true; - testMethodData.CanonicalDataCase.Expected = CanonicalDataValue.ExpectedToMultiLineString(testMethodData.CanonicalDataCase.Expected); - - if (testMethodData.CanonicalDataCase.Data.ContainsKey("end verse")) - testMethodData.CanonicalDataCase.Input = new[] { testMethodData.CanonicalDataCase.Data["start verse"], testMethodData.CanonicalDataCase.Data["end verse"] }; - else - testMethodData.Options.InputProperty = "start verse"; - - return testMethodData; - } - } -} \ No newline at end of file diff --git a/generators/Exercises/HelloWorld.cs b/generators/Exercises/HelloWorld.cs new file mode 100644 index 0000000000..db5c5ea266 --- /dev/null +++ b/generators/Exercises/HelloWorld.cs @@ -0,0 +1,6 @@ +namespace Generators.Exercises +{ + public class HelloWorld : Exercise + { + } +} diff --git a/generators/Exercises/HelloWorldExercise.cs b/generators/Exercises/HelloWorldExercise.cs deleted file mode 100644 index 2dc311a916..0000000000 --- a/generators/Exercises/HelloWorldExercise.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Generators.Exercises -{ - public class HelloWorldExercise : EqualityExercise - { - public HelloWorldExercise() : base("hello-world") - { - } - } -} diff --git a/generators/Exercises/Isogram.cs b/generators/Exercises/Isogram.cs new file mode 100644 index 0000000000..9a1eb0d57c --- /dev/null +++ b/generators/Exercises/Isogram.cs @@ -0,0 +1,6 @@ +namespace Generators.Exercises +{ + public class Isogram : Exercise + { + } +} \ No newline at end of file diff --git a/generators/Exercises/IsogramExercise.cs b/generators/Exercises/IsogramExercise.cs deleted file mode 100644 index ac422da9bc..0000000000 --- a/generators/Exercises/IsogramExercise.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Generators.Exercises -{ - public class IsogramExercise : BooleanExercise - { - public IsogramExercise() : base("isogram") - { - } - } -} \ No newline at end of file diff --git a/generators/Exercises/Leap.cs b/generators/Exercises/Leap.cs new file mode 100644 index 0000000000..867aef2c78 --- /dev/null +++ b/generators/Exercises/Leap.cs @@ -0,0 +1,11 @@ +namespace Generators.Exercises +{ + public class Leap : Exercise + { + public Leap() + { + foreach (var canonicalDataCase in CanonicalData.Cases) + canonicalDataCase.Property = "IsLeapYear"; + } + } +} \ No newline at end of file diff --git a/generators/Exercises/LeapExercise.cs b/generators/Exercises/LeapExercise.cs deleted file mode 100644 index b3689f4f7e..0000000000 --- a/generators/Exercises/LeapExercise.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Generators.Exercises -{ - public class LeapExercise : BooleanExercise - { - public LeapExercise() : base("leap") - { - } - } -} \ No newline at end of file diff --git a/generators/Exercises/Luhn.cs b/generators/Exercises/Luhn.cs new file mode 100644 index 0000000000..8ca010450c --- /dev/null +++ b/generators/Exercises/Luhn.cs @@ -0,0 +1,11 @@ +namespace Generators.Exercises +{ + public class Luhn : Exercise + { + public Luhn() + { + foreach (var canonicalDataCase in CanonicalData.Cases) + canonicalDataCase.Property = "IsValid"; + } + } +} diff --git a/generators/Exercises/LuhnExercise.cs b/generators/Exercises/LuhnExercise.cs deleted file mode 100644 index 7789f85571..0000000000 --- a/generators/Exercises/LuhnExercise.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Generators.Exercises -{ - public class LuhnExercise : BooleanExercise - { - public LuhnExercise() : base("luhn") - { - } - } -} diff --git a/generators/Exercises/NthPrime.cs b/generators/Exercises/NthPrime.cs new file mode 100644 index 0000000000..8b80055aca --- /dev/null +++ b/generators/Exercises/NthPrime.cs @@ -0,0 +1,13 @@ +using System; + +namespace Generators.Exercises +{ + public class NthPrime : Exercise + { + public NthPrime() + { + Configuration.ExceptionType = typeof(ArgumentOutOfRangeException); + Configuration.ThrowExceptionWhenExpectedValueEquals = x => x is bool; + } + } +} \ No newline at end of file diff --git a/generators/Exercises/NthPrimeExercise.cs b/generators/Exercises/NthPrimeExercise.cs deleted file mode 100644 index d1f887223a..0000000000 --- a/generators/Exercises/NthPrimeExercise.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using Generators.Data; -using Generators.Methods; - -namespace Generators.Exercises -{ - public class NthPrimeExercise : EqualityExercise - { - public NthPrimeExercise() : base("nth-prime") - { - } - - protected override TestMethodOptions CreateTestMethodOptions(CanonicalData canonicalData, CanonicalDataCase canonicalDataCase, int index) - { - var testMethodOptions = base.CreateTestMethodOptions(canonicalData, canonicalDataCase, index); - testMethodOptions.ExceptionType = typeof(ArgumentOutOfRangeException); - testMethodOptions.ThrowExceptionWhenExpectedValueEquals = x => x is bool; - - return testMethodOptions; - } - } -} \ No newline at end of file diff --git a/generators/Exercises/PerfectNumbers.cs b/generators/Exercises/PerfectNumbers.cs new file mode 100644 index 0000000000..13d511c421 --- /dev/null +++ b/generators/Exercises/PerfectNumbers.cs @@ -0,0 +1,25 @@ +using System; + +namespace Generators.Exercises +{ + public class PerfectNumbers : Exercise + { + public PerfectNumbers() + { + Configuration.ExceptionType = typeof(ArgumentOutOfRangeException); + + foreach (var canonicalDataCase in CanonicalData.Cases) + { + if (canonicalDataCase.Expected is string classificationType) + canonicalDataCase.Expected = Enum.Parse(typeof(Classification), classificationType, true); + } + } + + private enum Classification + { + Abundant, + Deficient, + Perfect, + } + } +} \ No newline at end of file diff --git a/generators/Exercises/PerfectNumbersExercise.cs b/generators/Exercises/PerfectNumbersExercise.cs deleted file mode 100644 index ba84988a81..0000000000 --- a/generators/Exercises/PerfectNumbersExercise.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using Generators.Data; -using Generators.Methods; -using Humanizer; - -namespace Generators.Exercises -{ - public class PerfectNumbersExercise : EqualityExercise - { - public PerfectNumbersExercise() : base("perfect-numbers") - { - } - - protected override TestMethodData CreateTestMethodData(CanonicalData canonicalData, CanonicalDataCase canonicalDataCase, int index) - { - var testMethodData = base.CreateTestMethodData(canonicalData, canonicalDataCase, index); - testMethodData.Options.ExceptionType = typeof(ArgumentOutOfRangeException); - testMethodData.Options.FormatExpected = false; - - if (testMethodData.CanonicalDataCase.Expected is string classificationType) - testMethodData.CanonicalDataCase.Expected = GetClassification(classificationType); - - return testMethodData; - } - - private static string GetClassification(string classificationType) - => $"Classification.{classificationType.Transform(Humanizer.To.TitleCase)}"; - } -} \ No newline at end of file diff --git a/generators/Exercises/PigLatin.cs b/generators/Exercises/PigLatin.cs new file mode 100644 index 0000000000..3f3c88e13c --- /dev/null +++ b/generators/Exercises/PigLatin.cs @@ -0,0 +1,6 @@ +namespace Generators.Exercises +{ + public class PigLatin : Exercise + { + } +} \ No newline at end of file diff --git a/generators/Exercises/PigLatinExercise.cs b/generators/Exercises/PigLatinExercise.cs deleted file mode 100644 index 7241affc9e..0000000000 --- a/generators/Exercises/PigLatinExercise.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Generators.Exercises -{ - public class PigLatinExercise : EqualityExercise - { - public PigLatinExercise() : base("pig-latin") - { - } - } -} \ No newline at end of file diff --git a/generators/Exercises/Raindrops.cs b/generators/Exercises/Raindrops.cs new file mode 100644 index 0000000000..27a80b7112 --- /dev/null +++ b/generators/Exercises/Raindrops.cs @@ -0,0 +1,6 @@ +namespace Generators.Exercises +{ + public class Raindrops : Exercise + { + } +} \ No newline at end of file diff --git a/generators/Exercises/RaindropsExercise.cs b/generators/Exercises/RaindropsExercise.cs deleted file mode 100644 index 502a940e05..0000000000 --- a/generators/Exercises/RaindropsExercise.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Generators.Data; -using Generators.Methods; - -namespace Generators.Exercises -{ - public class RaindropsExercise : EqualityExercise - { - public RaindropsExercise() : base("raindrops") - { - } - - protected override TestMethodOptions CreateTestMethodOptions(CanonicalData canonicalData, CanonicalDataCase canonicalDataCase, int index) - { - var testMethodOptions = base.CreateTestMethodOptions(canonicalData, canonicalDataCase, index); - testMethodOptions.InputProperty = "number"; - - return testMethodOptions; - } - } -} \ No newline at end of file diff --git a/generators/Exercises/RomanNumerals.cs b/generators/Exercises/RomanNumerals.cs new file mode 100644 index 0000000000..770595495e --- /dev/null +++ b/generators/Exercises/RomanNumerals.cs @@ -0,0 +1,16 @@ +namespace Generators.Exercises +{ + public class RomanNumerals : Exercise + { + public RomanNumerals() + { + Configuration.TestedMethodType = TestedMethodType.Extension; + + foreach (var canonicalDataCase in CanonicalData.Cases) + { + canonicalDataCase.Property = "ToRoman"; + canonicalDataCase.Description = "Number_" + canonicalDataCase.Description; + } + } + } +} \ No newline at end of file diff --git a/generators/Exercises/RomanNumeralsExercise.cs b/generators/Exercises/RomanNumeralsExercise.cs deleted file mode 100644 index 8dff638a42..0000000000 --- a/generators/Exercises/RomanNumeralsExercise.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Generators.Data; -using Generators.Methods; - -namespace Generators.Exercises -{ - public class RomanNumeralsExercise : EqualityExercise - { - public RomanNumeralsExercise() : base("roman-numerals") - { - } - - protected override TestMethodData CreateTestMethodData(CanonicalData canonicalData, CanonicalDataCase canonicalDataCase, int index) - { - var testMethodData = base.CreateTestMethodData(canonicalData, canonicalDataCase, index); - testMethodData.CanonicalDataCase.Property = "ToRoman"; - testMethodData.CanonicalDataCase.Description = "Number_" + testMethodData.CanonicalDataCase.Description; - - return testMethodData; - } - - protected override TestMethodOptions CreateTestMethodOptions(CanonicalData canonicalData, CanonicalDataCase canonicalDataCase, int index) - { - var testMethodOptions = new TestMethodOptions(); - testMethodOptions.InputProperty = "number"; - testMethodOptions.TestedMethodType = TestedMethodType.Extension; - - return testMethodOptions; - } - } -} \ No newline at end of file diff --git a/generators/Exercises/RotationalCipher.cs b/generators/Exercises/RotationalCipher.cs new file mode 100644 index 0000000000..6f71e13a4b --- /dev/null +++ b/generators/Exercises/RotationalCipher.cs @@ -0,0 +1,6 @@ +namespace Generators.Exercises +{ + public class RotationalCipher : Exercise + { + } +} \ No newline at end of file diff --git a/generators/Exercises/RotationalCipherExercise.cs b/generators/Exercises/RotationalCipherExercise.cs deleted file mode 100644 index 7cfdb3bfa8..0000000000 --- a/generators/Exercises/RotationalCipherExercise.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Generators.Data; -using Generators.Methods; - -namespace Generators.Exercises -{ - public class RotationalCipherExercise : EqualityExercise - { - public RotationalCipherExercise() : base("rotational-cipher") - { - } - - protected override TestMethodData CreateTestMethodData(CanonicalData canonicalData, CanonicalDataCase canonicalDataCase, int index) - { - var testMethodData = base.CreateTestMethodData(canonicalData, canonicalDataCase, index); - testMethodData.CanonicalDataCase.Input = new[] - { - testMethodData.CanonicalDataCase.Data["text"], - testMethodData.CanonicalDataCase.Data["shiftKey"] - }; - return testMethodData; - } - } -} \ No newline at end of file diff --git a/generators/Exercises/Wordy.cs b/generators/Exercises/Wordy.cs new file mode 100644 index 0000000000..fc234ad7b5 --- /dev/null +++ b/generators/Exercises/Wordy.cs @@ -0,0 +1,10 @@ +namespace Generators.Exercises +{ + public class Wordy : Exercise + { + public Wordy() + { + Configuration.ThrowExceptionWhenExpectedValueEquals = x => x is bool; + } + } +} \ No newline at end of file diff --git a/generators/Exercises/WordyExercise.cs b/generators/Exercises/WordyExercise.cs deleted file mode 100644 index befd927978..0000000000 --- a/generators/Exercises/WordyExercise.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Generators.Data; -using Generators.Methods; - -namespace Generators.Exercises -{ - public class WordyExercise : EqualityExercise - { - public WordyExercise() : base("wordy") - { - } - - protected override TestMethodOptions CreateTestMethodOptions(CanonicalData canonicalData, CanonicalDataCase canonicalDataCase, int index) - { - var testMethodOptions = base.CreateTestMethodOptions(canonicalData, canonicalDataCase, index); - testMethodOptions.ThrowExceptionWhenExpectedValueEquals = x => x is bool; - - return testMethodOptions; - } - } -} \ No newline at end of file diff --git a/generators/Generators.csproj b/generators/Generators.csproj index efab961ac0..4668aa5edc 100644 --- a/generators/Generators.csproj +++ b/generators/Generators.csproj @@ -4,9 +4,15 @@ netcoreapp1.1 - - + + + + + + Always + + \ No newline at end of file diff --git a/generators/Helpers/StringExtensions.cs b/generators/Helpers/StringExtensions.cs deleted file mode 100644 index b949f3186f..0000000000 --- a/generators/Helpers/StringExtensions.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Generators.Helpers -{ - public static class StringExtensions - { - public static string EnsureStartsWith(this string str, string value) - => str.StartsWith(value) ? str : value + str; - } -} \ No newline at end of file diff --git a/generators/Helpers/To.cs b/generators/Helpers/To.cs deleted file mode 100644 index b1a03ca62e..0000000000 --- a/generators/Helpers/To.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Generators.Classes; -using Generators.Methods; - -namespace Generators.Helpers -{ - public static class To - { - public static readonly TestedClassNameTransformer TestedClassName = new TestedClassNameTransformer(); - public static readonly TestClassNameTransformer TestClassName = new TestClassNameTransformer(); - public static readonly TestedMethodNameTransformer TestedMethodName = new TestedMethodNameTransformer(); - public static readonly TestMethodNameTransformer TestMethodName = new TestMethodNameTransformer(); - } -} \ No newline at end of file diff --git a/generators/Data/CanonicalData.cs b/generators/Input/CanonicalData.cs similarity index 81% rename from generators/Data/CanonicalData.cs rename to generators/Input/CanonicalData.cs index 577c96871e..eacb64aabe 100644 --- a/generators/Data/CanonicalData.cs +++ b/generators/Input/CanonicalData.cs @@ -1,7 +1,7 @@ using System.ComponentModel.DataAnnotations; using Newtonsoft.Json; -namespace Generators.Data +namespace Generators.Input { public class CanonicalData { @@ -11,8 +11,6 @@ public class CanonicalData [Required] public string Version { get; set; } - public string[] Comments { get; set; } - [JsonConverter(typeof(CanonicalDataCasesJsonConverter))] public CanonicalDataCase[] Cases { get; set; } } diff --git a/generators/Data/CanonicalDataCase.cs b/generators/Input/CanonicalDataCase.cs similarity index 68% rename from generators/Data/CanonicalDataCase.cs rename to generators/Input/CanonicalDataCase.cs index 081b535f61..162f9089d0 100644 --- a/generators/Data/CanonicalDataCase.cs +++ b/generators/Input/CanonicalDataCase.cs @@ -2,7 +2,7 @@ using System.ComponentModel.DataAnnotations; using Newtonsoft.Json; -namespace Generators.Data +namespace Generators.Input { [JsonConverter(typeof(CanonicalDataCaseJsonConverter))] public class CanonicalDataCase @@ -13,12 +13,9 @@ public class CanonicalDataCase [Required] public string Property { get; set; } - public string[] Comments { get; set; } - - public object Input { get; set; } + [JsonIgnore] + public IDictionary Input { get; set; } public object Expected { get; set; } - - public IDictionary Data { get; set; } } } \ No newline at end of file diff --git a/generators/Input/CanonicalDataCaseJsonConverter.cs b/generators/Input/CanonicalDataCaseJsonConverter.cs new file mode 100644 index 0000000000..a4b8573bf9 --- /dev/null +++ b/generators/Input/CanonicalDataCaseJsonConverter.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Generators.Input +{ + public class CanonicalDataCaseJsonConverter : JsonConverter + { + private static readonly string[] NonInputProperties = {"description", "property", "expected", "comments"}; + + public override bool CanConvert(Type objectType) => typeof(CanonicalDataCase) == objectType; + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + var jToken = JToken.ReadFrom(reader); + + var canonicalDataCase = new CanonicalDataCase(); + serializer.Populate(new JTokenReader(jToken), canonicalDataCase); + + canonicalDataCase.Input = GetInputProperties(jToken); + + return canonicalDataCase; + } + + private static IDictionary GetInputProperties(JToken jToken) + { + var allProperties = jToken.ToObject>(); + + foreach (var nonInputProperty in NonInputProperties) + allProperties.Remove(nonInputProperty); + + return allProperties; + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) => throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/generators/Data/CanonicalDataCasesJsonConverter.cs b/generators/Input/CanonicalDataCasesJsonConverter.cs similarity index 57% rename from generators/Data/CanonicalDataCasesJsonConverter.cs rename to generators/Input/CanonicalDataCasesJsonConverter.cs index 9092376425..273149c41b 100644 --- a/generators/Data/CanonicalDataCasesJsonConverter.cs +++ b/generators/Input/CanonicalDataCasesJsonConverter.cs @@ -1,30 +1,25 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Reflection; using Newtonsoft.Json; using Newtonsoft.Json.Linq; -namespace Generators.Data +namespace Generators.Input { public class CanonicalDataCasesJsonConverter : JsonConverter { - public override bool CanConvert(Type objectType) - { - return typeof(IEnumerable).GetTypeInfo().IsAssignableFrom(objectType); - } + private const string TokensPath = "$..*[?(@.property)]"; + + public override bool CanConvert(Type objectType) => typeof(IEnumerable).GetTypeInfo().IsAssignableFrom(objectType); public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var casesToken = JToken.ReadFrom(reader); - var caseTokens = casesToken.SelectTokens("$..*[?(@.property)]").ToArray(); + var caseTokens = new JArray(casesToken.SelectTokens(TokensPath)); return new JArray(caseTokens).ToObject(objectType); } - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - throw new NotImplementedException(); - } + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) => throw new NotImplementedException(); } } \ No newline at end of file diff --git a/generators/Data/CanonicalDataParser.cs b/generators/Input/CanonicalDataParser.cs similarity index 97% rename from generators/Data/CanonicalDataParser.cs rename to generators/Input/CanonicalDataParser.cs index d804eacaeb..5fffcf7c0f 100644 --- a/generators/Data/CanonicalDataParser.cs +++ b/generators/Input/CanonicalDataParser.cs @@ -3,7 +3,7 @@ using System.Net.Http; using Newtonsoft.Json; -namespace Generators.Data +namespace Generators.Input { public static class CanonicalDataParser { diff --git a/generators/Data/ExerciseCollection.cs b/generators/Input/ExerciseCollection.cs similarity index 71% rename from generators/Data/ExerciseCollection.cs rename to generators/Input/ExerciseCollection.cs index db96ec628f..0437ef226b 100644 --- a/generators/Data/ExerciseCollection.cs +++ b/generators/Input/ExerciseCollection.cs @@ -3,15 +3,14 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; -using Generators.Exercises; -namespace Generators.Data +namespace Generators.Input { public class ExerciseCollection : IEnumerable { - private readonly IEnumerable generators = GetDefinedGenerators(); + private readonly IEnumerable _generators = GetDefinedGenerators(); - public IEnumerator GetEnumerator() => generators.GetEnumerator(); + public IEnumerator GetEnumerator() => _generators.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); diff --git a/generators/Methods/BooleanTestMethodGenerator.cs b/generators/Methods/BooleanTestMethodGenerator.cs deleted file mode 100644 index 69b92c6ec4..0000000000 --- a/generators/Methods/BooleanTestMethodGenerator.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using Generators.Helpers; - -namespace Generators.Methods -{ - public class BooleanTestMethodGenerator : TestMethodGenerator - { - protected override string Body - { - get - { - switch (TestMethodData.Options.TestedMethodType) - { - case TestedMethodType.Static: - return $"{Assertion}({TestedClassName}.{TestedMethod}({Input}));"; - case TestedMethodType.Instance: - return $"var sut = new {TestedClassName}();\n {Assertion}(sut.{TestedMethod}({Input}));"; - case TestedMethodType.Extension: - return $"{Assertion}({Input}.{TestedMethod}());"; - default: - throw new ArgumentOutOfRangeException(); - } - } - } - - private string Assertion - => $"Assert.{Convert.ToBoolean(TestMethodData.CanonicalDataCase.Expected)}"; - - protected override string TestedMethod - => base.TestedMethod.EnsureStartsWith("Is"); - } -} \ No newline at end of file diff --git a/generators/Methods/EqualityTestMethodGenerator.cs b/generators/Methods/EqualityTestMethodGenerator.cs deleted file mode 100644 index d13e6b6210..0000000000 --- a/generators/Methods/EqualityTestMethodGenerator.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using System.Linq; - -namespace Generators.Methods -{ - public class EqualityTestMethodGenerator : TestMethodGenerator - { - private const string Tab = " "; - - protected override string Body - { - get - { - switch (TestMethodData.Options.TestedMethodType) - { - case TestedMethodType.Static: - if (TestMethodData.Options.UseVariableForExpected) - return $"var expected = {FormattedExpectedVariable};\nAssert.Equal(expected, {TestedClassName}.{TestedMethod}({Input}));"; - - return $"Assert.Equal({Expected}, {TestedClassName}.{TestedMethod}({Input}));"; - case TestedMethodType.Instance: - if (TestMethodData.Options.UseVariableForExpected) - return $"var expected = {FormattedExpectedVariable};\nvar sut = new {TestedClassName}();\n Assert.Equal({Expected}, sut.{TestedMethod}({Input}));"; - - return $"var sut = new {TestedClassName}();\n Assert.Equal({Expected}, sut.{TestedMethod}({Input}));"; - case TestedMethodType.Extension: - if (TestMethodData.Options.UseVariableForExpected) - return $"var expected = {FormattedExpectedVariable};\nAssert.Equal(expected, {Input}.{TestedMethod}());"; - - return $"Assert.Equal({Expected}, {Input}.{TestedMethod}());"; - default: - throw new ArgumentOutOfRangeException(); - } - } - } - - protected virtual string FormattedExpectedVariable - { - get - { - var lines = Expected.ToString().Split('\n'); - if (lines.Length == 1) - return lines[0]; - - return "\n" + string.Join("\n", lines.Select(line => $"{Tab}{line}")); - } - } - } -} \ No newline at end of file diff --git a/generators/Methods/ExceptionTestMethodGenerator.cs b/generators/Methods/ExceptionTestMethodGenerator.cs deleted file mode 100644 index 7117129d80..0000000000 --- a/generators/Methods/ExceptionTestMethodGenerator.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Generators.Methods -{ - public class ExceptionTestMethodGenerator : TestMethodGenerator - { - protected override string Body - { - get - { - switch (TestMethodData.Options.TestedMethodType) - { - case TestedMethodType.Static: - return $"Assert.Throws<{ExceptionType}>(() => {TestedClassName}.{TestedMethod}({Input}));"; - case TestedMethodType.Instance: - return $"var sut = new {TestedClassName}();\n Assert.Throws<{ExceptionType}>(() => sut.{TestedMethod}({Input}));;"; - case TestedMethodType.Extension: - return $"Assert.Throws<{ExceptionType}>(() => {Input}.{TestedMethod}());"; - default: - throw new ArgumentOutOfRangeException(); - } - } - } - - protected override ISet UsingNamespaces => new HashSet { TestMethodData.Options.ExceptionType.Namespace }; - - protected virtual string ExceptionType => TestMethodData.Options.ExceptionType.Name; - } -} \ No newline at end of file diff --git a/generators/Methods/TestMethod.cs b/generators/Methods/TestMethod.cs deleted file mode 100644 index ae87a55301..0000000000 --- a/generators/Methods/TestMethod.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Collections.Generic; - -namespace Generators.Methods -{ - public class TestMethod - { - public ISet UsingNamespaces { get; set; } = new HashSet(); - public string MethodName { get; set; } - public string Body { get; set; } - public int Index { get; set; } - } -} \ No newline at end of file diff --git a/generators/Methods/TestMethodData.cs b/generators/Methods/TestMethodData.cs deleted file mode 100644 index c60e011000..0000000000 --- a/generators/Methods/TestMethodData.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Generators.Data; - -namespace Generators.Methods -{ - public class TestMethodData - { - public CanonicalData CanonicalData { get; set; } - public CanonicalDataCase CanonicalDataCase { get; set;} - public int Index { get; set; } - public TestMethodOptions Options { get; set; } = new TestMethodOptions(); - } -} \ No newline at end of file diff --git a/generators/Methods/TestMethodGenerator.cs b/generators/Methods/TestMethodGenerator.cs deleted file mode 100644 index ec17643a6d..0000000000 --- a/generators/Methods/TestMethodGenerator.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Humanizer; -using To = Generators.Helpers.To; - -namespace Generators.Methods -{ - public abstract class TestMethodGenerator - { - public TestMethod Create(TestMethodData testMethodData) - { - TestMethodData = testMethodData; - - return new TestMethod - { - MethodName = MethodName, - Body = Body, - Index = TestMethodData.Index, - UsingNamespaces = UsingNamespaces - }; - } - - protected TestMethodData TestMethodData { get; private set; } - - protected abstract string Body { get; } - - protected virtual ISet UsingNamespaces - => new HashSet(); - - protected virtual string MethodName - => TestMethodData.CanonicalDataCase.Description.Replace(":", " is").Transform(To.TestMethodName); - - protected virtual string TestedClassName - => TestMethodData.CanonicalData.Exercise.Transform(To.TestedClassName); - - protected virtual string TestedMethod - => TestMethodData.CanonicalDataCase.Property.Transform(To.TestedMethodName); - - protected virtual object Input => - TestMethodData.Options.FormatInput - ? FormatInputValue(InputValue) - : InputValue; - - protected virtual object Expected => - TestMethodData.Options.FormatExpected - ? FormatValue(TestMethodData.CanonicalDataCase.Expected) - : TestMethodData.CanonicalDataCase.Expected; - - protected virtual object InputValue => - TestMethodData.Options.InputProperty == null - ? TestMethodData.CanonicalDataCase.Input - : TestMethodData.CanonicalDataCase.Data[TestMethodData.Options.InputProperty]; - - protected virtual object FormatValue(object val) - { - switch (val) - { - case string s: - s = s - .Replace("\n", "\\n") - .Replace("\r", "\\r") - .Replace("\t", "\\t"); - return $"\"{s}\""; - default: - return val; - } - } - - protected virtual object FormatInputValue(object val) - { - switch (val) - { - case IEnumerable inputs when !(val is string): - return string.Join(", ", inputs.Select(FormatValue)); - default: - return FormatValue(val); - } - } - } -} \ No newline at end of file diff --git a/generators/Methods/TestMethodNameTransformer.cs b/generators/Methods/TestMethodNameTransformer.cs deleted file mode 100644 index f75685bc9c..0000000000 --- a/generators/Methods/TestMethodNameTransformer.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Text.RegularExpressions; -using Humanizer; - -namespace Generators.Methods -{ - public class TestMethodNameTransformer : IStringTransformer - { - public string Transform(string input) - { - var methodName = Regex.Replace(input, @"[^\w]+", "_", RegexOptions.Compiled) - .Underscore() - .Transform(To.TitleCase); - - if (char.IsDigit(methodName[0])) - return "Number_" + methodName; - - if (!char.IsLetter(methodName[0])) - return "Test_"; - - return methodName; - } - } -} \ No newline at end of file diff --git a/generators/Methods/TestMethodOptions.cs b/generators/Methods/TestMethodOptions.cs deleted file mode 100644 index c39397ec86..0000000000 --- a/generators/Methods/TestMethodOptions.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; - -namespace Generators.Methods -{ - public class TestMethodOptions - { - public string InputProperty { get; set; } - public bool FormatInput { get; set; } = true; - public bool FormatExpected { get; set; } = true; - public bool UseVariableForExpected { get; set; } = false; - public Type ExceptionType { get; set; } = typeof(ArgumentException); - public TestedMethodType TestedMethodType { get; set; } = TestedMethodType.Static; - public Func ThrowExceptionWhenExpectedValueEquals { get; set; } = (x) => false; - } -} \ No newline at end of file diff --git a/generators/Methods/TestMethodRenderer.cs b/generators/Methods/TestMethodRenderer.cs deleted file mode 100644 index 1be927eb57..0000000000 --- a/generators/Methods/TestMethodRenderer.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Linq; - -namespace Generators.Methods -{ - public static class TestMethodRenderer - { - private const string Tab = " "; - - private const string TestMethodTemplate = -@"{Tab}[Fact{Skip}] -{Tab}public void {Name}() -{Tab}{ -{Body} -{Tab}}"; - - public static string Render(TestMethod testMethod) => - TestMethodTemplate - .Replace("{Tab}", Tab) - .Replace("{Name}", testMethod.MethodName) - .Replace("{Body}", RenderBody(testMethod)) - .Replace("{Skip}", testMethod.Index == 0 ? "" : "(Skip = \"Remove to run test\")"); - - private static string RenderBody(TestMethod testMethod) - => string.Join("\n", testMethod.Body.Split('\n').Select(line => $"{Tab}{Tab}{line}")); - } -} diff --git a/generators/Methods/TestedMethodNameTransformer.cs b/generators/Methods/TestedMethodNameTransformer.cs deleted file mode 100644 index 1417d33b52..0000000000 --- a/generators/Methods/TestedMethodNameTransformer.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Humanizer; - -namespace Generators.Methods -{ - public class TestedMethodNameTransformer : IStringTransformer - { - public string Transform(string input) => input.Dehumanize(); - } -} \ No newline at end of file diff --git a/generators/Output/BooleanTestMethodGenerator.cs b/generators/Output/BooleanTestMethodGenerator.cs new file mode 100644 index 0000000000..7d20334190 --- /dev/null +++ b/generators/Output/BooleanTestMethodGenerator.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; + +namespace Generators.Output +{ + public class BooleanTestMethodGenerator : TestMethodGenerator + { + protected override IEnumerable Body + { + get + { + switch (Configuration.TestedMethodType) + { + case TestedMethodType.Static: + return new[] { $"{Assertion}({TestedClassName}.{TestedMethodName}({Input}));" }; + case TestedMethodType.Instance: + return new[] { $"var sut = new {TestedClassName}();", $"{Assertion}(sut.{TestedMethodName}({Input}));" }; + case TestedMethodType.Extension: + return new[] { $"{Assertion}({Input}.{TestedMethodName}());" }; + default: + throw new ArgumentOutOfRangeException(); + } + } + } + + private string Assertion => $"Assert.{Convert.ToBoolean(CanonicalDataCase.Expected)}"; + } +} \ No newline at end of file diff --git a/generators/Output/EqualityTestMethodGenerator.cs b/generators/Output/EqualityTestMethodGenerator.cs new file mode 100644 index 0000000000..b46a1a42d0 --- /dev/null +++ b/generators/Output/EqualityTestMethodGenerator.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Generators.Output +{ + public class EqualityTestMethodGenerator : TestMethodGenerator + { + protected override IEnumerable Body + { + get + { + switch (Configuration.TestedMethodType) + { + case TestedMethodType.Static: + if (UseVariableForExpected) + return ExpectedVariableDeclaration.Concat(new[] { $"Assert.Equal(expected, {TestedClassName}.{TestedMethodName}({Input}));" }); + + return new[] { $"Assert.Equal({Expected}, {TestedClassName}.{TestedMethodName}({Input}));" }; + case TestedMethodType.Instance: + if (UseVariableForExpected) + return ExpectedVariableDeclaration.Concat(new[] { $"var sut = new {TestedClassName}();", $"Assert.Equal(expected, sut.{TestedMethodName}({Input}));" }); + + return new[] { $"var sut = new {TestedClassName}();", $"Assert.Equal({Expected}, sut.{TestedMethodName}({Input}));" }; + case TestedMethodType.Extension: + if (UseVariableForExpected) + return ExpectedVariableDeclaration.Concat(new[] { $"Assert.Equal(expected, {Input}.{TestedMethodName}());" }); + + return new[] { $"Assert.Equal({Expected}, {Input}.{TestedMethodName}());" }; + default: + throw new ArgumentOutOfRangeException(); + } + } + } + } +} \ No newline at end of file diff --git a/generators/Output/ExceptionTestMethodGenerator.cs b/generators/Output/ExceptionTestMethodGenerator.cs new file mode 100644 index 0000000000..56b0908fc0 --- /dev/null +++ b/generators/Output/ExceptionTestMethodGenerator.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; + +namespace Generators.Output +{ + public class ExceptionTestMethodGenerator : TestMethodGenerator + { + protected override IEnumerable Body + { + get + { + switch (Configuration.TestedMethodType) + { + case TestedMethodType.Static: + return new[] { $"Assert.Throws<{ExceptionType}>(() => {TestedClassName}.{TestedMethodName}({Input}));" }; + case TestedMethodType.Instance: + return new[] { $"var sut = new {TestedClassName}();", $"Assert.Throws<{ExceptionType}>(() => sut.{TestedMethodName}({Input}));" }; + case TestedMethodType.Extension: + return new[] { $"Assert.Throws<{ExceptionType}>(() => {Input}.{TestedMethodName}());" }; + default: + throw new ArgumentOutOfRangeException(); + } + } + } + + protected virtual string ExceptionType => Configuration.ExceptionType.FullName; + } +} \ No newline at end of file diff --git a/generators/Output/MultiLineString.cs b/generators/Output/MultiLineString.cs new file mode 100644 index 0000000000..c56ef6c671 --- /dev/null +++ b/generators/Output/MultiLineString.cs @@ -0,0 +1,20 @@ +using System.Collections; +using System.Collections.Generic; + +namespace Generators.Output +{ + public class MultiLineString : IEnumerable + { + private readonly IEnumerable _lines; + + public MultiLineString(string str) : this(str.Split('\n')) + { + } + + public MultiLineString(IEnumerable lines) => _lines = lines; + + public IEnumerator GetEnumerator() => _lines.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } +} \ No newline at end of file diff --git a/generators/Output/NameExtensions.cs b/generators/Output/NameExtensions.cs new file mode 100644 index 0000000000..84066b8b1b --- /dev/null +++ b/generators/Output/NameExtensions.cs @@ -0,0 +1,30 @@ +using System.Text.RegularExpressions; +using Humanizer; + +namespace Generators.Output +{ + public static class NameExtensions + { + public static string ToTestClassName(this string input) => $"{input.Dehumanize()}Test"; + + public static string ToTestedClassName(this string input) => input.Dehumanize(); + + public static string ToTestMethodName(this string input) + { + var methodName = + Regex.Replace(input.Replace(":", " is"), @"[^\w]+", "_", RegexOptions.Compiled) + .Underscore() + .Transform(To.TitleCase); + + if (char.IsDigit(methodName[0])) + return "Number_" + methodName; + + if (!char.IsLetter(methodName[0])) + return "Test_"; + + return methodName; + } + + public static string ToTestedMethodName(this string input) => input.Dehumanize(); + } +} \ No newline at end of file diff --git a/generators/Output/TestClass.cs b/generators/Output/TestClass.cs new file mode 100644 index 0000000000..f2fa1bd6e4 --- /dev/null +++ b/generators/Output/TestClass.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; + +namespace Generators.Output +{ + public class TestClass + { + public string ClassName { get; set; } + public string CanonicalDataVersion { get; set; } + public TestMethod[] TestMethods { get; set; } + public ISet UsingNamespaces { get; } = new HashSet { "Xunit" }; + } +} \ No newline at end of file diff --git a/generators/Output/TestClass.liquid b/generators/Output/TestClass.liquid new file mode 100644 index 0000000000..c779f058e0 --- /dev/null +++ b/generators/Output/TestClass.liquid @@ -0,0 +1,20 @@ +// This file was auto-generated based on version {{CanonicalDataVersion}} of the canonical data. + +{%- for namespace in UsingNamespaces -%} +using {{ namespace }}; +{%- endfor -%} + +public class {{ClassName}} +{ +{%- for testMethod in TestMethods -%} + [Fact{% if forloop.first == false %}(Skip = "Remove to run test"){% endif %}] + public void {{testMethod.Name}}() + { + {%- for line in testMethod.Body -%} + {{ line }} + {%- endfor -%} + } +{%- if forloop.last == false %} +{% endif -%} +{%- endfor -%} +} \ No newline at end of file diff --git a/generators/Output/TestClassFile.cs b/generators/Output/TestClassFile.cs new file mode 100644 index 0000000000..bf1e90f06f --- /dev/null +++ b/generators/Output/TestClassFile.cs @@ -0,0 +1,22 @@ +using System.IO; +using Serilog; + +namespace Generators.Output +{ + public static class TestClassFile + { + public static void Write(Exercise exercise, string contents) + { + var testClassFilePath = TestClassFilePath(exercise); + + Directory.CreateDirectory(Path.GetDirectoryName(testClassFilePath)); + File.WriteAllText(testClassFilePath, contents); + + Log.Information("Generated tests for {Exercise} exercise in {TestFile}.", exercise.Name, testClassFilePath); + } + + private static string TestClassFilePath(Exercise exercise) => Path.Combine("..", "exercises", exercise.Name, TestClassFileName(exercise)); + + private static string TestClassFileName(Exercise exercise) => $"{exercise.Name.ToTestClassName()}.cs"; + } +} \ No newline at end of file diff --git a/generators/Output/TestClassGenerator.cs b/generators/Output/TestClassGenerator.cs new file mode 100644 index 0000000000..7c610260fd --- /dev/null +++ b/generators/Output/TestClassGenerator.cs @@ -0,0 +1,30 @@ +using System.Linq; +using Generators.Input; + +namespace Generators.Output +{ + public static class TestClassGenerator + { + private static readonly BooleanTestMethodGenerator BooleanTestMethod = new BooleanTestMethodGenerator(); + private static readonly EqualityTestMethodGenerator EqualityTestMethod = new EqualityTestMethodGenerator(); + private static readonly ExceptionTestMethodGenerator ExceptionTestMethod = new ExceptionTestMethodGenerator(); + + public static TestClass Create(Exercise exercise) => new TestClass + { + ClassName = exercise.Name.ToTestClassName(), + TestMethods = exercise.CanonicalData.Cases.Select(canonicalDataCase => CreateTestMethod(canonicalDataCase, exercise)).ToArray(), + CanonicalDataVersion = exercise.CanonicalData.Version + }; + + private static TestMethod CreateTestMethod(CanonicalDataCase canonicalDataCase, Exercise exercise) + { + if (exercise.Configuration.ThrowExceptionWhenExpectedValueEquals(canonicalDataCase.Expected)) + return ExceptionTestMethod.Create(canonicalDataCase, exercise); + + if (canonicalDataCase.Expected is bool) + return BooleanTestMethod.Create(canonicalDataCase, exercise); + + return EqualityTestMethod.Create(canonicalDataCase, exercise); + } + } +} diff --git a/generators/Output/TestClassRenderer.cs b/generators/Output/TestClassRenderer.cs new file mode 100644 index 0000000000..8cf155dc43 --- /dev/null +++ b/generators/Output/TestClassRenderer.cs @@ -0,0 +1,26 @@ +using System.IO; +using System.Linq; +using DotLiquid; + +namespace Generators.Output +{ + public static class TestClassRenderer + { + private static readonly string TemplateContents = File.ReadAllText(Path.Combine("Output", "TestClass.liquid")); + + private static readonly Template TestClassTemplate = Template.Parse(TemplateContents); + + public static string Render(TestClass testClass) + { + var templateData = new + { + CanonicalDataVersion = testClass.CanonicalDataVersion, + UsingNamespaces = testClass.UsingNamespaces, + ClassName = testClass.ClassName, + TestMethods = testClass.TestMethods.Select(testMethod => new { Name = testMethod.MethodName, Body = testMethod.Body }) + }; + + return TestClassTemplate.Render(Hash.FromAnonymousObject(templateData)); + } + } +} diff --git a/generators/Output/TestMethod.cs b/generators/Output/TestMethod.cs new file mode 100644 index 0000000000..bd60ff910b --- /dev/null +++ b/generators/Output/TestMethod.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; + +namespace Generators.Output +{ + public class TestMethod + { + public string MethodName { get; set; } + public IEnumerable Body { get; set; } + } +} \ No newline at end of file diff --git a/generators/Output/TestMethodGenerator.cs b/generators/Output/TestMethodGenerator.cs new file mode 100644 index 0000000000..fa4d2600af --- /dev/null +++ b/generators/Output/TestMethodGenerator.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; +using Generators.Input; + +namespace Generators.Output +{ + public abstract class TestMethodGenerator + { + public TestMethod Create(CanonicalDataCase canonicalDataCase, Exercise exercise) + { + CanonicalDataCase = canonicalDataCase; + CanonicalData = exercise.CanonicalData; + Configuration = exercise.Configuration; + + return new TestMethod { MethodName = TestMethodName, Body = Body }; + } + + protected abstract IEnumerable Body { get; } + + protected CanonicalDataCase CanonicalDataCase { get; private set; } + protected CanonicalData CanonicalData { get; private set; } + protected ExerciseConfiguration Configuration { get; private set; } + + protected string TestMethodName => CanonicalDataCase.Description.ToTestMethodName(); + protected string TestedClassName => CanonicalData.Exercise.ToTestedClassName(); + protected string TestedMethodName => CanonicalDataCase.Property.ToTestedMethodName(); + + protected object Input => ValueFormatter.Format(CanonicalDataCase.Input); + protected object Expected => ValueFormatter.Format(CanonicalDataCase.Expected); + protected IEnumerable ExpectedVariableDeclaration => ValueFormatter.FormatVariable(CanonicalDataCase.Expected); + protected bool UseVariableForExpected => CanonicalDataCase.Expected is MultiLineString; + } +} \ No newline at end of file diff --git a/generators/Output/ValueFormatter.cs b/generators/Output/ValueFormatter.cs new file mode 100644 index 0000000000..305765effc --- /dev/null +++ b/generators/Output/ValueFormatter.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Generators.Output +{ + public static class ValueFormatter + { + public static object Format(object val) + { + switch (val) + { + case IDictionary dict: + return string.Join(", ", dict.Values.Select(Format)); + case Enum enumeration: + return $"{enumeration.GetType().Name}.{enumeration}";; + case IEnumerable strings: + return strings.Select(FormatString); + case string str: + return str.FormatString(); + default: + return val; + } + } + + public static IEnumerable FormatVariable(object val) + { + switch (val) + { + case MultiLineString multiLineString: + var lines = new List {"var expected = "}; + return lines.Concat( + multiLineString + .Select((t, i) => i < multiLineString.Count() - 1 + ? $" {Format(t + "\n")} +" + : $" {Format(t)};")); + default: + return new[] {$"var expected = {Format(val)};"}; + } + } + + private static string FormatString(this string s) => s.EscapeControlCharacters().Quote(); + + private static string EscapeControlCharacters(this string s) + => s.Replace("\n", "\\n") + .Replace("\t", "\\t") + .Replace("\r", "\\r"); + + private static string Quote(this string s) => $"\"{s}\""; + } +} \ No newline at end of file diff --git a/generators/Program.cs b/generators/Program.cs index a96395f769..695dc8fcac 100644 --- a/generators/Program.cs +++ b/generators/Program.cs @@ -1,7 +1,4 @@ -using Generators.Exercises; -using System.IO; -using Generators.Classes; -using Generators.Data; +using Generators.Input; using Serilog; namespace Generators @@ -23,44 +20,12 @@ private static void SetupLogger() private static void GenerateAll() { - Log.Information("Start generating tests..."); - - TestFileGenerator.Generate(new FoodChainExercise()); + Log.Information("Generating tests..."); foreach (var exercise in new ExerciseCollection()) - TestFileGenerator.Generate(exercise); - - Log.Information("Finished generating tests for all supported exercises."); - } - } - - public static class TestFileGenerator - { - public static void Generate(Exercise exercise) - { - var testClass = CreateTestClass(exercise); - var testClassContents = TestClassRenderer.Render(testClass); - var testClassFilePath = TestFilePath(exercise, testClass); - - SaveTestClassContentsToFile(testClassFilePath, testClassContents); - Log.Information("Generated tests for {Exercise} exercise in {TestFile}.", exercise.Name, testClassFilePath); - } + exercise.Generate(); - private static TestClass CreateTestClass(Exercise exercise) - { - var canonicalData = CanonicalDataParser.Parse(exercise.Name); - return exercise.CreateTestClass(canonicalData); + Log.Information("Generated tests."); } - - private static void SaveTestClassContentsToFile(string testClassFilePath, string testClassContents) - { - Directory.CreateDirectory(Path.GetDirectoryName(testClassFilePath)); - File.WriteAllText(testClassFilePath, testClassContents); - } - - - private static string TestFilePath(Exercise exercise, TestClass testClass) => Path.Combine("..", "exercises", exercise.Name, TestFileName(testClass)); - - private static string TestFileName(TestClass testClass) => $"{testClass.ClassName}.cs"; } } \ No newline at end of file diff --git a/generators/Methods/TestedMethodType.cs b/generators/TestedMethodType.cs similarity index 77% rename from generators/Methods/TestedMethodType.cs rename to generators/TestedMethodType.cs index 90a66e2875..0e8938029d 100644 --- a/generators/Methods/TestedMethodType.cs +++ b/generators/TestedMethodType.cs @@ -1,4 +1,4 @@ -namespace Generators.Methods +namespace Generators { public enum TestedMethodType {