Let's Make a Language: C♭ - Part 3
Shame on me.
I know you caught it in that Let's Make a Language: C♭ - Part 2.
I didn’t write any tests. Not a one.
Shame on me.
Convert ignominy to esteem
Let’s rectify the situation by writing some tests to make sure that our code does what we want it to do and to safeguard against future side effects. You can download the 20111213.zip as a starting point.
Create the test project
If you’re following along and using Monodevelop, add a new C# “NUnit Library Project” named “cflat.tests”. This comes with NUnit 2.4.8, so the includes will differ from the newer version of NUnit.
If you’re following along and using Visual Studio 2010, download and install NUnit, create a new C# “Library” named “cflat.tests”, and add a reference to the NUnit library installed in the GAC or locally.
If you’re not following along, then go back to your baba ghanouj and skate.
Now, add to the “cflat.tests” project a reference to the “cflat” project.
Rename the default file to “Needs300LinesTests.cs” and ensure the contents of the file look a lot like this.
1 | using System; |
Black-box testing
I elect to perform black-box testing on the cflat project. This means that I won’t test the inner functions, just test it through the publicly exposed API. In this case, an executable, that means running a process.
This is very different from unit testing. I just want to make that clear.
Success scenario
First off, let’s test the good case, that a file of more than 300 lines exists, the C♭ transcompiler will consume it, and we should get no message on stderr and the return code should equal 0. Test-writing time.
1 | [ ] |
I get a big ol’ green light when I run that test.
Failing scenario
Let’s do the same thing but with a file that contains 299 new-line characters. Copy-And-Paste Commando says:
1 | [ ] |
Again, big ol’ green light. Sweet!
Refactoring
Ok, Copy-And-Paste Commando: BAD. So, let’s fix the test file. We can extract
the file generation and the process bootstrapping. Really, if we can test the
content of the process’ stderr and its exit code, our assertions will change
very little. So, move all of that repeated, boilerplate, file-generating,
process-starting code out of both methods into a method named
CreateFileAndRunCompilerOnIt(int)
. And, Shazam!
1 | [ ] |
That improves the code’s comprehensibility by a gazillion.
You can download the final code for this post at 20111214.zip.