trackler 2.2.1.134 → 2.2.1.135
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/trackler/version.rb +1 -1
- data/problem-specifications/exercises/series/canonical-data.json +105 -0
- data/problem-specifications/exercises/series/description.md +6 -6
- data/problem-specifications/exercises/sieve/description.md +5 -3
- data/tracks/ceylon/exercises/sieve/README.md +5 -3
- data/tracks/fsharp/.gitignore +1 -0
- data/tracks/fsharp/docs/GENERATORS.md +314 -0
- data/tracks/fsharp/generators/Exercise.fs +39 -80
- data/tracks/fsharp/generators/Generators.fs +42 -40
- data/tracks/fsharp/generators/Generators.fsproj.user +6 -0
- data/tracks/haskell/exercises/crypto-square/README.md +4 -5
- data/tracks/haskell/exercises/isbn-verifier/package.yaml +1 -1
- data/tracks/haskell/exercises/isbn-verifier/test/Tests.hs +4 -0
- data/tracks/haskell/exercises/kindergarten-garden/package.yaml +1 -1
- data/tracks/haskell/exercises/series/README.md +6 -6
- data/tracks/haskell/exercises/series/examples/success-byteseqs/src/Series.hs +6 -8
- data/tracks/haskell/exercises/series/examples/success-standard/src/Series.hs +0 -1
- data/tracks/haskell/exercises/series/package.yaml +1 -1
- data/tracks/haskell/exercises/series/test/Tests.hs +17 -2
- data/tracks/haskell/exercises/sieve/README.md +5 -3
- data/tracks/java/CONTRIBUTING.md +5 -6
- data/tracks/java/exercises/book-store/.meta/version +1 -1
- data/tracks/java/exercises/change/.meta/version +1 -1
- data/tracks/java/exercises/circular-buffer/.meta/version +1 -1
- data/tracks/java/exercises/custom-set/.meta/version +1 -1
- data/tracks/java/exercises/forth/.meta/version +1 -1
- data/tracks/java/exercises/list-ops/.meta/version +1 -1
- data/tracks/java/exercises/minesweeper/.meta/version +1 -1
- data/tracks/java/exercises/ocr-numbers/.meta/version +1 -1
- data/tracks/java/exercises/wordy/.meta/version +1 -1
- data/tracks/nim/config.json +57 -44
- data/tracks/nim/exercises/pangram/README.md +26 -0
- data/tracks/nim/exercises/pangram/example.nim +9 -0
- data/tracks/nim/exercises/pangram/pangram_test.nim +35 -0
- data/tracks/nim/exercises/roman-numerals/README.md +61 -0
- data/tracks/nim/exercises/roman-numerals/example.nim +30 -0
- data/tracks/nim/exercises/roman-numerals/roman_numerals_test.nim +28 -0
- data/tracks/nim/exercises/scrabble-score/README.md +57 -0
- data/tracks/nim/exercises/scrabble-score/example.nim +13 -0
- data/tracks/nim/exercises/scrabble-score/scrabble_score_test.nim +37 -0
- data/tracks/perl5/README.md +2 -1
- data/tracks/perl5/cpanfile +2 -1
- data/tracks/perl5/exercises/grains/.meta/exercise-data.yaml +55 -0
- data/tracks/perl5/exercises/grains/.meta/solutions/Grains.pm +15 -23
- data/tracks/perl5/exercises/grains/Grains.pm +13 -0
- data/tracks/perl5/exercises/grains/cpanfile +1 -0
- data/tracks/perl5/exercises/grains/grains.t +136 -75
- data/tracks/ruby/README.md +0 -6
- data/tracks/rust/.travis.yml +1 -1
- data/tracks/rust/_test/check-stubs.sh +0 -0
- data/tracks/rust/_test/count-ignores.sh +0 -0
- data/tracks/rust/_test/ensure-lib-src-rs-exist.sh +0 -0
- data/tracks/rust/_test/ensure-readmes-are-updated.sh +0 -0
- data/tracks/rust/_test/ensure-stubs-compile.sh +0 -0
- data/tracks/rust/_test/verify-exercise-difficulties.sh +52 -0
- data/tracks/rust/config.json +4 -4
- data/tracks/swift/exercises/space-age/Tests/SpaceAgeTests/SpaceAgeTests.swift +15 -15
- data/tracks/typescript/config.json +46 -1
- data/tracks/typescript/exercises/bowling/README.md +93 -0
- data/tracks/typescript/exercises/bowling/bowling.example.ts +77 -0
- data/tracks/typescript/exercises/bowling/bowling.test.ts +137 -0
- data/tracks/typescript/exercises/bowling/bowling.ts +0 -0
- data/tracks/typescript/exercises/bowling/package.json +36 -0
- data/tracks/typescript/exercises/bowling/tsconfig.json +22 -0
- data/tracks/typescript/exercises/bowling/tslint.json +127 -0
- data/tracks/typescript/exercises/bowling/yarn.lock +2624 -0
- data/tracks/typescript/exercises/connect/README.md +59 -0
- data/tracks/typescript/exercises/connect/connect.example.ts +77 -0
- data/tracks/typescript/exercises/connect/connect.test.ts +108 -0
- data/tracks/typescript/exercises/connect/connect.ts +0 -0
- data/tracks/typescript/exercises/connect/package.json +36 -0
- data/tracks/typescript/exercises/connect/tsconfig.json +22 -0
- data/tracks/typescript/exercises/connect/tslint.json +127 -0
- data/tracks/typescript/exercises/connect/yarn.lock +2624 -0
- data/tracks/typescript/exercises/rectangles/README.md +92 -0
- data/tracks/typescript/exercises/rectangles/package.json +36 -0
- data/tracks/typescript/exercises/rectangles/rectangles.example.ts +59 -0
- data/tracks/typescript/exercises/rectangles/rectangles.test.ts +134 -0
- data/tracks/typescript/exercises/rectangles/rectangles.ts +0 -0
- data/tracks/typescript/exercises/rectangles/tsconfig.json +22 -0
- data/tracks/typescript/exercises/rectangles/tslint.json +127 -0
- data/tracks/typescript/exercises/rectangles/yarn.lock +2624 -0
- metadata +42 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e668f282132d63c1231f79fddb5137f51faf314e
|
4
|
+
data.tar.gz: 127deef6f4aa01b28b4b74330f9826aed28fa24c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 04c5e56a00719b737739a8490682bafee1888a1879a26a4a6b008ad301e5df2811d223bcf5f6cf819b834366863087b92dd77b78dd4ab524c7fe83e6dc31f3ca
|
7
|
+
data.tar.gz: d5dfc98f5a4349fa1c383b66f954eaeed399eb836f40fac6bde8a57531572c3b05513e2b59ab33e4b91761d5c5592f4f827d80532fdb684d9e84524e56151d15
|
data/lib/trackler/version.rb
CHANGED
@@ -0,0 +1,105 @@
|
|
1
|
+
{
|
2
|
+
"exercise": "series",
|
3
|
+
"version": "1.0.0",
|
4
|
+
"cases": [
|
5
|
+
{
|
6
|
+
"description": "slices of one from one",
|
7
|
+
"property": "slices",
|
8
|
+
"input": {
|
9
|
+
"series": "1",
|
10
|
+
"sliceLength": 1
|
11
|
+
},
|
12
|
+
"expected": ["1"]
|
13
|
+
},
|
14
|
+
{
|
15
|
+
"description": "slices of one from two",
|
16
|
+
"property": "slices",
|
17
|
+
"input": {
|
18
|
+
"series": "12",
|
19
|
+
"sliceLength": 1
|
20
|
+
},
|
21
|
+
"expected": ["1", "2"]
|
22
|
+
},
|
23
|
+
{
|
24
|
+
"description": "slices of two",
|
25
|
+
"property": "slices",
|
26
|
+
"input": {
|
27
|
+
"series": "35",
|
28
|
+
"sliceLength": 2
|
29
|
+
},
|
30
|
+
"expected": ["35"]
|
31
|
+
},
|
32
|
+
{
|
33
|
+
"description": "slices of two overlap",
|
34
|
+
"property": "slices",
|
35
|
+
"input": {
|
36
|
+
"series": "9142",
|
37
|
+
"sliceLength": 2
|
38
|
+
},
|
39
|
+
"expected": ["91", "14", "42"]
|
40
|
+
},
|
41
|
+
{
|
42
|
+
"description": "slices can include duplicates",
|
43
|
+
"property": "slices",
|
44
|
+
"input": {
|
45
|
+
"series": "777777",
|
46
|
+
"sliceLength": 3
|
47
|
+
},
|
48
|
+
"expected": ["777", "777", "777", "777"]
|
49
|
+
},
|
50
|
+
{
|
51
|
+
"description": "slices of a long series",
|
52
|
+
"property": "slices",
|
53
|
+
"input": {
|
54
|
+
"series": "918493904243",
|
55
|
+
"sliceLength": 5
|
56
|
+
},
|
57
|
+
"expected": ["91849", "18493", "84939", "49390",
|
58
|
+
"93904", "39042", "90424", "04243"]
|
59
|
+
},
|
60
|
+
{
|
61
|
+
"description": "slice length is too large",
|
62
|
+
"property": "slices",
|
63
|
+
"input": {
|
64
|
+
"series": "12345",
|
65
|
+
"sliceLength": 6
|
66
|
+
},
|
67
|
+
"expected": {
|
68
|
+
"error": "slice length cannot be greater than series length"
|
69
|
+
}
|
70
|
+
},
|
71
|
+
{
|
72
|
+
"description": "slice length cannot be zero",
|
73
|
+
"property": "slices",
|
74
|
+
"input": {
|
75
|
+
"series": "12345",
|
76
|
+
"sliceLength": 0
|
77
|
+
},
|
78
|
+
"expected": {
|
79
|
+
"error": "slice length cannot be zero"
|
80
|
+
}
|
81
|
+
},
|
82
|
+
{
|
83
|
+
"description": "slice length cannot be negative",
|
84
|
+
"property": "slices",
|
85
|
+
"input": {
|
86
|
+
"series": "123",
|
87
|
+
"sliceLength": -1
|
88
|
+
},
|
89
|
+
"expected": {
|
90
|
+
"error": "slice length cannot be negative"
|
91
|
+
}
|
92
|
+
},
|
93
|
+
{
|
94
|
+
"description": "empty series is invalid",
|
95
|
+
"property": "slices",
|
96
|
+
"input": {
|
97
|
+
"series": "",
|
98
|
+
"sliceLength": 1
|
99
|
+
},
|
100
|
+
"expected": {
|
101
|
+
"error": "series cannot be empty"
|
102
|
+
}
|
103
|
+
}
|
104
|
+
]
|
105
|
+
}
|
@@ -1,16 +1,16 @@
|
|
1
1
|
Given a string of digits, output all the contiguous substrings of length `n` in
|
2
|
-
that string.
|
2
|
+
that string in the order that they appear.
|
3
3
|
|
4
4
|
For example, the string "49142" has the following 3-digit series:
|
5
5
|
|
6
|
-
- 491
|
7
|
-
- 914
|
8
|
-
- 142
|
6
|
+
- "491"
|
7
|
+
- "914"
|
8
|
+
- "142"
|
9
9
|
|
10
10
|
And the following 4-digit series:
|
11
11
|
|
12
|
-
- 4914
|
13
|
-
- 9142
|
12
|
+
- "4914"
|
13
|
+
- "9142"
|
14
14
|
|
15
15
|
And if you ask for a 6-digit series from a 5-digit string, you deserve
|
16
16
|
whatever you get.
|
@@ -3,8 +3,8 @@ number.
|
|
3
3
|
|
4
4
|
The Sieve of Eratosthenes is a simple, ancient algorithm for finding all
|
5
5
|
prime numbers up to any given limit. It does so by iteratively marking as
|
6
|
-
composite (i.e. not prime) the multiples of each prime,
|
7
|
-
|
6
|
+
composite (i.e. not prime) the multiples of each prime, starting with the
|
7
|
+
multiples of 2. It does not use any division or remainder operation.
|
8
8
|
|
9
9
|
Create your range, starting at two and continuing up to and including the given limit. (i.e. [2, limit])
|
10
10
|
|
@@ -23,4 +23,6 @@ https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
|
|
23
23
|
|
24
24
|
Notice that this is a very specific algorithm, and the tests don't check
|
25
25
|
that you've implemented the algorithm, only that you've come up with the
|
26
|
-
correct list of primes.
|
26
|
+
correct list of primes. A good first test is to check that you do not use
|
27
|
+
division or remainder operations (div, /, mod or % depending on the
|
28
|
+
language).
|
@@ -5,8 +5,8 @@ number.
|
|
5
5
|
|
6
6
|
The Sieve of Eratosthenes is a simple, ancient algorithm for finding all
|
7
7
|
prime numbers up to any given limit. It does so by iteratively marking as
|
8
|
-
composite (i.e. not prime) the multiples of each prime,
|
9
|
-
|
8
|
+
composite (i.e. not prime) the multiples of each prime, starting with the
|
9
|
+
multiples of 2. It does not use any division or remainder operation.
|
10
10
|
|
11
11
|
Create your range, starting at two and continuing up to and including the given limit. (i.e. [2, limit])
|
12
12
|
|
@@ -25,7 +25,9 @@ https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
|
|
25
25
|
|
26
26
|
Notice that this is a very specific algorithm, and the tests don't check
|
27
27
|
that you've implemented the algorithm, only that you've come up with the
|
28
|
-
correct list of primes.
|
28
|
+
correct list of primes. A good first test is to check that you do not use
|
29
|
+
division or remainder operations (div, /, mod or % depending on the
|
30
|
+
language).
|
29
31
|
|
30
32
|
## Running Ceylon Tests
|
31
33
|
|
data/tracks/fsharp/.gitignore
CHANGED
@@ -0,0 +1,314 @@
|
|
1
|
+
# Test Generators
|
2
|
+
|
3
|
+
Test generators allow tracks to generate tests automatically without having to write them ourselves. Each test generator reads from the exercise's `canonical data`, which defines the name of the test, its inputs, and outputs. You can read more about exercism's approach to test suites [here](https://github.com/exercism/docs/blob/master/language-tracks/exercises/anatomy/test-suites.md).
|
4
|
+
|
5
|
+
Generating tests automatically removes any sort of user error when creating tests. We want the tests to be accurate with respect to its canonical data. Test generation also makes it much easier to keep tests up to date. As the canonical data changes, the tests will be automatically updated when the generator for that test is run.
|
6
|
+
|
7
|
+
An example of a canonical data file can be found [here](https://github.com/exercism/problem-specifications/blob/master/exercises/bob/canonical-data.json)
|
8
|
+
|
9
|
+
## Common Terms
|
10
|
+
|
11
|
+
When looking through the canonical data and the generator code base, we use a lot of common terminology. This list hopefully clarifies what they represent.
|
12
|
+
|
13
|
+
* Canonical Data - Represents the entire test suite.
|
14
|
+
* Canonical Data Case - A representation of a single test case.
|
15
|
+
* Description - The name of the test.
|
16
|
+
* Property - The method to be called when running the test.
|
17
|
+
* Input - The input for the test case.
|
18
|
+
* Expected - The expected value when running the test case.
|
19
|
+
|
20
|
+
## Adding a simple generator
|
21
|
+
|
22
|
+
Adding a test generator is straightforward. Simply add a class to the `Generators.fs` file in the `generators` folder with the name of the exercise (in PascalCase), and extend the `GeneratorExercise` abstract class.
|
23
|
+
|
24
|
+
An example of a simple generator would be the Bob exercise. The source code can be found below, but you can also view it in the repository [here](https://github.com/exercism/fsharp/blob/master/generators/Generators.fs#L174).
|
25
|
+
|
26
|
+
```fsharp
|
27
|
+
type Bob() =
|
28
|
+
inherit GeneratorExercise()
|
29
|
+
```
|
30
|
+
|
31
|
+
This is a fully working generator, no other code needs to be written. However, it's simplicity stems from the fact that the test suite and the program itself are relatively trivial.
|
32
|
+
|
33
|
+
## Adding a complex generator
|
34
|
+
|
35
|
+
For many generators, the default behavior of the `GeneratorExercise` class suffices. However, for more _complex_ generators, one can override one or more of its virtual methods:
|
36
|
+
|
37
|
+
### Method: RenderInput
|
38
|
+
|
39
|
+
Render the input of a test method.
|
40
|
+
|
41
|
+
#### Example
|
42
|
+
|
43
|
+
The `Gigasecond` generator renders the input value as a (parenthesized) `DateTime` value:
|
44
|
+
|
45
|
+
```fsharp
|
46
|
+
override __.RenderInput (canonicalDataCase, key, value) =
|
47
|
+
DateTime.Parse(string value, CultureInfo.InvariantCulture)
|
48
|
+
|> formatDateTime
|
49
|
+
|> parenthesize
|
50
|
+
```
|
51
|
+
|
52
|
+
Note that you could use the `key` field to only customize the output for specific input fields. The `Yacht` generator does this:
|
53
|
+
|
54
|
+
```fsharp
|
55
|
+
override __.RenderInput (canonicalDataCase, key, value) =
|
56
|
+
match key with
|
57
|
+
| "category" -> sprintf "Category.%s" (string value |> String.dehumanize)
|
58
|
+
| _ -> base.RenderInput (canonicalDataCase, key, value)
|
59
|
+
```
|
60
|
+
|
61
|
+
### Method: RenderExpected
|
62
|
+
|
63
|
+
Render the expected value of a test method.
|
64
|
+
|
65
|
+
#### Example
|
66
|
+
|
67
|
+
The `Connect` generator renders the expected value as an `Option<T>` value:
|
68
|
+
|
69
|
+
```fsharp
|
70
|
+
override __.RenderExpected (canonicalDataCase, key, value) =
|
71
|
+
match string value with
|
72
|
+
| "O" -> "(Some White)"
|
73
|
+
| "X" -> "(Some Black)"
|
74
|
+
| _ -> "None"
|
75
|
+
```
|
76
|
+
|
77
|
+
### Method: RenderSut
|
78
|
+
|
79
|
+
Render the System Under Test (SUT). This is the actual value that is verified against the expected value.
|
80
|
+
|
81
|
+
#### Example
|
82
|
+
|
83
|
+
The `RunLengthEncoding` generator has a test case where it verifies that encoding and then decoding the input results in the same value. The `RenderSut` method is overridden to convert what would be a single call to a non-existing `consistency` function, to a chain of `encode |> decode` calls:
|
84
|
+
|
85
|
+
```fsharp
|
86
|
+
override this.RenderSut canonicalDataCase =
|
87
|
+
match canonicalDataCase.Property with
|
88
|
+
| "consistency" ->
|
89
|
+
let parameters = this.RenderSutParameters canonicalDataCase |> String.concat " "
|
90
|
+
sprintf "%s |> encode |> decode" parameters
|
91
|
+
| _ ->
|
92
|
+
base.RenderSut canonicalDataCase
|
93
|
+
```
|
94
|
+
|
95
|
+
### Method: RenderArrange
|
96
|
+
|
97
|
+
Render the arrange part of the test method. In this part, the SUT is created.
|
98
|
+
|
99
|
+
The default behavior is usually what you want. Only in very special circumstances would you want to change this.
|
100
|
+
|
101
|
+
Note: this method returns a `string list`, where each `string` corresponds to a single, rendered line in the test file.
|
102
|
+
|
103
|
+
### Method: RenderAssert
|
104
|
+
|
105
|
+
Render the assert part of the test method. In this part, the assertion is made to verify the SUT against the expected value.
|
106
|
+
|
107
|
+
The default behavior is usually what you want. Only in very special circumstances would you want to change this.
|
108
|
+
|
109
|
+
Note: this method returns a `string list`, where each `string` corresponds to a single, rendered line in the test file.
|
110
|
+
|
111
|
+
### Method: RenderSetup
|
112
|
+
|
113
|
+
Render any additional utility/setup methods. This can be used to define helper methods that can be used in the test methods.
|
114
|
+
|
115
|
+
The setup code is added _before_ the test methods, to enable the setup methods to be used in the test methods.
|
116
|
+
|
117
|
+
Note: this method returns a `string list`, where each `string` corresponds to a single, rendered line in the test file.
|
118
|
+
|
119
|
+
#### Example
|
120
|
+
|
121
|
+
The `Zipper` generator adds two helper methods that are used in the test methods to remove some tedious, boilerplate code:
|
122
|
+
|
123
|
+
```fsharp
|
124
|
+
override __.RenderSetup _ =
|
125
|
+
[ "let subTree value left right = Some (tree value left right)"
|
126
|
+
"let leaf value = subTree value None None" ]
|
127
|
+
|> String.concat "\n"
|
128
|
+
```
|
129
|
+
|
130
|
+
### Method: RenderValue
|
131
|
+
|
132
|
+
Render a single value (which is used to render input parameters, the expected value and the SUT).
|
133
|
+
|
134
|
+
### Example
|
135
|
+
|
136
|
+
The `ComplexNumbers` generator renders different values based on the value's type:
|
137
|
+
|
138
|
+
```fsharp
|
139
|
+
override __.RenderValue (canonicalDataCase, key, value) =
|
140
|
+
match value with
|
141
|
+
| :? JArray as jArray -> renderComplexNumber jArray
|
142
|
+
| :? int64 as i -> sprintf "%d.0" i
|
143
|
+
| _ -> base.RenderValue (canonicalDataCase, key, value)
|
144
|
+
```
|
145
|
+
|
146
|
+
### Method: MapCanonicalDataCase
|
147
|
+
|
148
|
+
Map the canonical data case. This can be useful if you want to add or remove properties.
|
149
|
+
|
150
|
+
The default behavior is usually what you want. Only in very special circumstances would you want to change this.
|
151
|
+
|
152
|
+
#### Example
|
153
|
+
|
154
|
+
The `ScaleGenerator` generator uses the canonical data case mapping to add a missing property as a `null` value (which makes processing later easier):
|
155
|
+
|
156
|
+
```fsharp
|
157
|
+
override __.MapCanonicalDataCase canonicalDataCase =
|
158
|
+
let input = canonicalDataCase.Input
|
159
|
+
match Map.tryFind "intervals" input with
|
160
|
+
| Some _ -> canonicalDataCase
|
161
|
+
| None -> { canonicalDataCase with Input = Map.add "intervals" null input }
|
162
|
+
```
|
163
|
+
|
164
|
+
### Method: PropertiesUsedAsSutParameter
|
165
|
+
|
166
|
+
Specifies which properties should be used as parameters to the SUT.
|
167
|
+
|
168
|
+
The default behavior is usually what you want. Only in very special circumstances would you want to change this.
|
169
|
+
|
170
|
+
#### Example
|
171
|
+
|
172
|
+
The `RailFenceCipher` explicitly defines the properties used as SUT parameters to change the order in which they are passed:
|
173
|
+
|
174
|
+
```fsharp
|
175
|
+
override __.PropertiesUsedAsSutParameter _ = ["rails"; "msg"]
|
176
|
+
```
|
177
|
+
|
178
|
+
### Method: PropertiesWithIdentifier
|
179
|
+
|
180
|
+
Specifies which properties should have an identifier assigned to them. If a property is in this list, it will be assigned its value on a separate line, to its own identifier.
|
181
|
+
|
182
|
+
#### Example
|
183
|
+
|
184
|
+
The `Transpose` generator has chosen to use identifiers for all properties:
|
185
|
+
|
186
|
+
```fsharp
|
187
|
+
override this.PropertiesWithIdentifier canonicalDataCase = this.Properties canonicalDataCase
|
188
|
+
```
|
189
|
+
|
190
|
+
### Method: IdentifierTypeAnnotation
|
191
|
+
|
192
|
+
In some cases, you want an identifier to have an explicit type. A common use case is when a value is an empty list. In those case, FsUnit needs a type annotation for it to successfully execute the assertion.
|
193
|
+
|
194
|
+
#### Example
|
195
|
+
|
196
|
+
The `Minesweeper` generator adds a `string list` type annotation for empty values:
|
197
|
+
|
198
|
+
```fsharp
|
199
|
+
override __.IdentifierTypeAnnotation (_, _, value) =
|
200
|
+
match value :?> JArray |> Seq.isEmpty with
|
201
|
+
| true -> Some "string list"
|
202
|
+
| false -> None
|
203
|
+
```
|
204
|
+
|
205
|
+
### Method: AdditionalNamespaces
|
206
|
+
|
207
|
+
Returns a list of additional namespaces to open in the test file.
|
208
|
+
|
209
|
+
#### Example
|
210
|
+
|
211
|
+
The `Gigasecond` generator works with `DateTime` instances, and thus adds its namespace to the additional namespaces list:
|
212
|
+
|
213
|
+
```fsharp
|
214
|
+
override __.AdditionalNamespaces = [typeof<DateTime>.Namespace]
|
215
|
+
```
|
216
|
+
|
217
|
+
### Method: AssertTemplate
|
218
|
+
|
219
|
+
The assert template to use. You can find the full list of assert templates in `generators/Templates/_Assert*.liquid`
|
220
|
+
|
221
|
+
#### Example
|
222
|
+
|
223
|
+
The `RationalNumbers` generator uses the `"AssertEqualWithin"` template to allow for checking doubles for equality with a specific tolerance:
|
224
|
+
|
225
|
+
```fsharp
|
226
|
+
override __.AssertTemplate canonicalDataCase =
|
227
|
+
match canonicalDataCase.Expected with
|
228
|
+
| :? double -> "AssertEqualWithin"
|
229
|
+
| _ -> base.TestMethodBodyAssertTemplate(canonicalDataCase)
|
230
|
+
```
|
231
|
+
|
232
|
+
### Method: TestFileFormat
|
233
|
+
|
234
|
+
The test file's format: either a module or a class.
|
235
|
+
|
236
|
+
The default behavior is virtually always what you want. Only in extremely rare cases would you want to change this.
|
237
|
+
|
238
|
+
#### Example
|
239
|
+
|
240
|
+
The `Grep` generator defines itself as a test class to allow using setup and teardown methods:
|
241
|
+
|
242
|
+
```fsharp
|
243
|
+
override __.TestFileFormat = TestFileFormat.Class
|
244
|
+
```
|
245
|
+
|
246
|
+
### Method: TestMethodName
|
247
|
+
|
248
|
+
Specifies the test method's name.
|
249
|
+
|
250
|
+
The default behavior is usually what you want. Only in very special circumstances would you want to change this.
|
251
|
+
|
252
|
+
#### Example
|
253
|
+
|
254
|
+
The `Zipper` generator does some test method name cleanup:
|
255
|
+
|
256
|
+
```fsharp
|
257
|
+
override __.RenderTestMethodName canonicalDataCase =
|
258
|
+
let testMethodName = base.RenderTestMethodName canonicalDataCase
|
259
|
+
testMethodName.Replace("Set_", "Set ")
|
260
|
+
```
|
261
|
+
|
262
|
+
### Method: UseFullMethodName
|
263
|
+
|
264
|
+
Indicates if the test method name that is used should use the full path, which means that for nested test cases, it will prepend the test method name with the parent(s) description(s).
|
265
|
+
|
266
|
+
The default behavior is usually what you want. Only in cases where there would otherwise be multiple test methods with the same name would you want to change this.
|
267
|
+
|
268
|
+
#### Method: Signature
|
269
|
+
|
270
|
+
The `KindergartenGarden` generator uses full method names to prevent test method name clashes:
|
271
|
+
|
272
|
+
```fsharp
|
273
|
+
override __.UseFullMethodName _ = true
|
274
|
+
```
|
275
|
+
|
276
|
+
### Method: SkipTestMethod
|
277
|
+
|
278
|
+
Indicates if the test method should be marked with the `Skip = true` property.
|
279
|
+
|
280
|
+
The default behavior is virtually always what you want. Only in extremely rare cases would you want to change this.
|
281
|
+
|
282
|
+
#### Method: Signature
|
283
|
+
|
284
|
+
The `Markdown` exercises is a refactoring exercise, and as such all its tests should already be in a valid state. Therefore, it doesn't add the `Skip` property for any of its test methods:
|
285
|
+
|
286
|
+
```fsharp
|
287
|
+
override __.SkipTestMethod (_, _) = false
|
288
|
+
```
|
289
|
+
|
290
|
+
## Updating existing files
|
291
|
+
|
292
|
+
It is possible that an existing exercise does not match the canonical data. It is OK to update the exercise stub and/or the exercise example to follow the canonical data!
|
293
|
+
|
294
|
+
Also, if you find an issue with one of the existing generators or test suites simply open up the generator that you would like to update, make your changes, and then run the generators.
|
295
|
+
|
296
|
+
## Running the generators
|
297
|
+
|
298
|
+
This repository is coded against [.NET Core 2.x](https://www.microsoft.com/net/core). To run the generators all you need to do is run the following command in the generators directory:
|
299
|
+
|
300
|
+
`dotnet run`
|
301
|
+
|
302
|
+
This command will take all of the exercise generators that are defined, and generate all of the test cases for each exercise. We use reflection to get all of the exercises, so if you are adding a new test, the test will be automatically included when running the generator.
|
303
|
+
|
304
|
+
If you only need to run a single generator, you can do so by running the following command:
|
305
|
+
|
306
|
+
`dotnet run -e <exercise>`
|
307
|
+
|
308
|
+
Once the generator has been run, you can view the output of your generation by navigating to the test file for that exercise. As an example, the test suite for the Bob exercise can be found at:
|
309
|
+
|
310
|
+
`exercises/bob/BobTest.fs`
|
311
|
+
|
312
|
+
## Submitting a generator
|
313
|
+
|
314
|
+
If you are satisfied with the output of your generator, we would love for you to submit a pull request! Please include your generator, updated test suite, and any other corresponding files that you may have changed.
|