You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* generators: Ignore Rider settings files
* generators: Refactor additional namespaces
* exercises: Update to latest canonical data
* exercises: Use Array.Empty<T> instead of new T[0]
* generators: Use static class
* generators: Remove unused using statements
* generators: Move exercise field to canonical data case class
* generators: Use environment specific newline
* generators: Fix culture-specific output
* generators: Replace UpdateCanonicalData with UpdateCanonicalDataCase
* generators: Test method body rendering methods return IEnumerable<string>
* generators: Use var everywhere
* generator: Code cleanup
* generators: Remove unused parameter
* generators: Move variables data to TestMethodData
* generators: Make canonical data class immutable
* generators: Extract rendering logic from test data to test method body
* generators: Replace Exercise and Property with TestedClass and TestedMethod
* generators: Update package versions
* generators: Don't use sealed
* generators: Use UpdateTestClass/UpdateTestMethod/UpdateTestMethodBody to customize output
* exercises: Sort namespaces
* generator: Make GeneratorExercise API more consistent
* generators: Remove unneeded initialization
* generators: Rename ExerciseWriter to TestClassFile
* generators: Move template specific code to separate namespace
* generators: Move helpers to separate namespace
* generators: Remove unneeded generator scripts
* generators: Update namespace
* generators: Add separate test method for empty assertion
* generators: Improve naming of test method body implementations
* generators: Don't use assert template parameters in generators
* generators: Use consistent naming for TestMethodBody parameter
* generators: Simplified test method and class code
* generators: Make lifecycle of update methods be more sane
* generators: Simplify triangle generator
* generators: Introduce multiline string type
* generators: Remove dynamic extensions
* generators: Remove type extensions
* generators: Simplify description path logic
* generators: Move JToken conversion helpers to separate class
* generators: Fix invalid ordering of test case when nesting is used
* generators: Remove unused conversion cases
* generators: Remove convert helper
* generators: Introduce assertion rendering helper
* generators: Revert to using string as render output
* generators: Use assertion helpers
* generators: Add throws assertion generic overload
* generators: Use standard value formatter in binary search tree generator
* generators: Introduce rendering namespace
* generators: Add enum rendering helper
* generators: Rename Format to Render
* generators: Move rendering logic to separate partial classes
* generators: Make list rendering generic
* generators: Make array rendering generic
* generators: Make dictionary rendering generic
* generators: Improved friendly name generation
* generators: Make multidimensional array rendering generic
* generators: Make tuple rendering generic
* isbn-verifier: Update tests
* generators: Add friendly name support for char and array types
* generators: Refactor dictionary variable rendering
* maintainers: Update ErikSchierboom info (#599)
* maintainers: Update ErikSchierboom info
* generators: Refactor dictionary variable rendering
* generators: Refactor multi-line string (variable) rendering
* generators: Simplify binary search tree generator
* generators: Have variable rendering only return single value
* generators: Use Environment.Newline where possible
* generators: Simplify ocr-numbers generator
* generators: Refactor array variable rendering
* generators: Remove unused methods
* generators: Simplify string/char escaping code
* generators: Add collection initialization renderer
* generators: Use variable render helper to render variables
* generators: Fix simple-cipher generator
* generators: Refactor generators
* generators: Correctly render null value
* generators: Return correct friendly name for Nullable<T> and ValueTuple<T> types
* generators: Allow forced formatting of multi-line array
* generators: Fix list-ops nested empty list
* generators: Add missing namespace to nucleotide-count generator
* generators: Fix failing grep example implementation
* exercises: Use shorthand notation for ValueTuple
* generators: Fix multiline rendering not handling null references
* generators: Make TestClassFile static
* generators: Merge TestData with TestMethod
* generators: Move TestClass and TestMethod rendering output to separate class
* generators: Extract different property handling paths to separate methods
* generators: Simplify flatten-array generator
* generators: Refactor test method output
* generators: Update docs
* generators: Add missing links to docs and use consistent naming
* go-counting: Add space between operators in example implementation
* generators: Use consistent formatting of input and expected values for minesweeper
* generators: Increase length for single-line array initializers
* generators: Remove automatic multi-line rendering for one-dimensional arrays
* generators: Update docs
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
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.
5
+
Generating tests automatically removes any sort of user error when creating tests. Furthermore, 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
6
7
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
8
9
-
## Common Terms
9
+
## Common terms
10
+
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.
11
12
12
13
- Canonical Data - Represents the entire test suite.
@@ -16,87 +17,232 @@ When looking through the canonical data and the generator code base, we use a lo
16
17
- Input - The input for the test case.
17
18
- Expected - The expected value when running the test case.
18
19
19
-
## Adding A Simple Generator
20
-
Adding a test generator file is straightforward. Simply add a new file to the generators folder with the name of the exercise (in PascalCase), and extend the `GeneratorExercise` abstract class.
20
+
## Adding a simple generator
21
+
22
+
Adding a test generator is straightforward. Simply add a new file to the `Exercises/Generators` folder with the name of the exercise (in PascalCase), and create a class that extends the `GeneratorExercise` class.
21
23
22
-
An example of a simple generator would be the Bob exercise. The source is below, but you can freely view it in the repository [here](https://github.com/exercism/csharp/blob/master/generators/Exercises/Bob.cs).
24
+
An example of a simple generator would be the Bob exercise. The source is displayed below, but you can freely view it in the repository [here](https://github.com/exercism/csharp/blob/master/generators/Exercises/Bob.cs).
23
25
24
26
```csharp
25
-
namespaceGenerators.Exercises
27
+
namespaceExercism.CSharp.Exercises.Generators
26
28
{
27
29
publicclassBob : GeneratorExercise
28
30
{
29
31
}
30
32
}
31
33
```
32
34
33
-
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.
35
+
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.
36
+
37
+
## Adding a complex generator
34
38
35
-
## Adding A Complex Generator
39
+
When the generator's default output is not sufficient, you can override the `GeneratorExercise` class' virtual methods to override the default behavior.
36
40
37
-
A more *complex* generator would be the ComplexNumbers generator found [here](https://github.com/exercism/csharp/blob/master/generators/Exercises/ComplexNumbers.cs).
The `GeneratorExercise` abstract class currently exposes five methods that are used for overriding the default behavior when generating an exercise.
43
+
Update the test method that described the test method being generated. When you are required to customize a test generator, overriding this method is virtually always what you want to do.
There are many things that can be customized, of which we'll list the more common usages.
43
46
44
-
The most common use for this override is to iterate over each of the canonical data cases.
47
+
#### Customize test data
45
48
46
-
As an example, if you wanted to change the default behavior so that when the `Input` value of a test is a negative number, an exception should be thrown, the code would look like this.
49
+
It is not uncommon that a generator has to transform its input data or expected value to a different value/representation.
50
+
51
+
An example of this is the [bracket-push](https://github.com/exercism/csharp/blob/master/generators/Exercises/Generators/BracketPush.cs) generator, which has a `"value"` input value, which is of type `string`. However, this `string` value contains a backslash, which needs to escaped in order for it to be rendered correctly:
Allows more namespaces to be added to the test suite.
61
+
Another common use case is to handle empty arrays. If an array is empty, its type will default to `JArray`, which doesn't have any type information. To allow the generator to output a correctly typed array, we have to convert the `JArray` to an array first.
61
62
62
-
The tests use `Xunit` so all tests will automatically include the `Xunit` namespace. However, more advanced tests may require additional namespaces.
63
+
An example of this is the [proverb](https://github.com/exercism/csharp/blob/master/generators/Exercises/Generators/Proverb.cs) generator, which converts the `JArray` to an empty `string` array:
Sometimes, it might make sense to not define a test method's data inline, but as variables.
81
+
82
+
An example of this is the [crypto-square](https://github.com/exercism/csharp/blob/master/generators/Exercises/Generators/CryptoSquare.cs) generator, which indicates that both the test method input as well as the expected value, should be stored in variables:
By default, the generator will test a static method. However, you can also test for instance methods, extension methods, properties and constructors.
95
+
96
+
An example of this is the [roman-numerals](https://github.com/exercism/csharp/blob/master/generators/Exercises/Generators/RomanNumerals.cs) generator, which indicates that it tests an extensions method:
This snippet would add the namespace that the `Dictionary<char, int>` collection lives in (`System.Collections.Generic`).
106
+
#### Change names used
107
+
108
+
As we saw in the previous example, you can also customize the name of the tested method. You are also allowed to customize the tested class' name and the test method name.
Override the default behavior when rendering a test methods arrange, act, and/or assert sections.
110
+
An example of this is the [triangle](https://github.com/exercism/csharp/blob/master/generators/Exercises/Generators/Triangle.cs) generator, which by default generates duplicate test method names (which will be a compile-time error), but instead uses the `TestMethodNameWithPath` to use the full path as the test method name (effectively making the test method name unique):
More advanced tests may need to leverage a `template`. A template allows you to add additional code to a test and assert more complex statements.
121
+
#### Test for an exception being thrown
80
122
81
-
An example of this is the [RunLengthEncoding](https://github.com/exercism/csharp/blob/master/generators/Exercises/RunLengthEncoding.cs) test.
123
+
Some test methods want to verify that an exception is being thrown.
82
124
83
-
Here the **Assert**is being overridden. The assert needs to call additional functions, but only if the property is `consistency`. Otherwise, render the assert as usual.
125
+
An example of this is the [rna-transcription](https://github.com/exercism/csharp/blob/master/generators/Exercises/Generators/RnaTranscription.cs) generator, which defines that some of its test methods should throw an `ArgumentException`:
84
126
85
-
### string[] RenderAdditionalMethods()
86
-
Allow additional methods to be added to the test suite.
There may exist cases where a suite of unit tests will need to reuse the same logic in each of the tests. Rather than duplicating code, this method allows you to provide helper methods for the tests.
135
+
Note that `ArgumentException` type's namespace will be automatically added to the list of namespaces used in the test class.
89
136
90
-
An example of this is the [Tournament](https://github.com/exercism/csharp/blob/master/generators/Exercises/Tournament.cs#L45) generator.
137
+
#### Custom input/constructor parameters
91
138
92
-
Additional methods added using this override will be added to the bottom of the test suite.
139
+
In some cases, you might want to override the parameters that are used as input parameters.
140
+
141
+
An example of this is the [two-fer](https://github.com/exercism/csharp/blob/master/generators/Exercises/Generators/TwoFer.cs) generator, which does not use any input parameters when the `"name"` input parameter is set to `null`:
If a test method tests an instance method, you can also specify which parameters to use as constructor parameters (the others will be input parameters, unless specified otherwise).
154
+
155
+
An example of this is the [matrix](https://github.com/exercism/csharp/blob/master/generators/Exercises/Generators/Matrix.cs) generator, which specifies that the `"string"` parameter should be passed as a constructor parameter:
Although this should be used as a last resort, some generators might want to skip the default generation completely and control which arrange, act or assert code the test method should contain.
168
+
169
+
An example of this is the [run-length-encoding](https://github.com/exercism/csharp/blob/master/generators/Exercises/Generators/RunLengthEncoding.cs) generator, which uses a custom assertion for one specific property:
Allows additional namespaces to be added to the test suite.
193
+
194
+
All tests use the `Xunit` framework, so each test class will automatically include the `Xunit` namespace. However, some test classes may require additional namespaces.
195
+
196
+
An example of this is the [gigasecond](https://github.com/exercism/csharp/blob/master/generators/Exercises/Generators/Gigasecond.cs) generator, which uses the `DateTime` class in its test methods, and thus adds its namespace to the list of namespaces:
This method allows you to customize the output of the test class. Only in rare cases would you want to override this method. The most common use case to override this method, is to add additional (helper) methods to the test suite.
210
+
211
+
An example of this is the [tournament](https://github.com/exercism/csharp/blob/master/generators/Exercises/Generators/Tournament.cs) generator, which adds a helper method to the test suite:
using (var inStream = new MemoryStream(encoding.GetBytes(input)))
227
+
using (var outStream = new MemoryStream())
228
+
{
229
+
Tournament.Tally(inStream, outStream);
230
+
return encoding.GetString(outStream.ToArray());
231
+
}
232
+
}");
233
+
}
234
+
```
235
+
236
+
Additional methods will be added to the bottom of the test suite.
93
237
94
238
## Updating Existing Files
239
+
95
240
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! An example might be that an exercise is named SumOfMultiples, but the SumOfMultiples.cs and Example.cs files both use `Multiples` as the name of the class.
96
241
97
242
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.
98
243
99
244
## Running The Generators
245
+
100
246
This repository is coded against [.NET Core](https://www.microsoft.com/net/core). To run the generators all you need to do is run the following command in the generators directory:
101
247
102
248
`dotnet run`
@@ -112,4 +258,5 @@ Once the generator has been run, you can view the output of your generation by n
112
258
`exercises/bob/BobTest.cs`
113
259
114
260
## Submitting A Generator
261
+
115
262
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.
0 commit comments