This week, I was working on writing tests for my Shinny-SSG project. It was the most challenging lab in the OSD600 course since I had to modify both my code and my project's folder structure to implement the tests.
Set-up
The testing framework that I chose is XUnit. The first reason is that it is trendy compared to another test framework such as NUnits. I created test method stubs from the existing code by Create Unit Tests command. To use it with Xunit, I have to implement the XUnit.net.TestGenerator extension to my project.
Challenges
I want to test how my tools generated files and folders in the destination with different arguments passed to the program. However, in my old code, I put all the logic of working with arguments in the static int main( string[] args)
function. I could not use Interface and Dependency injection to mock the CommandLineApplication because CommandLineUtils does not have an interface for this class. Luckily, I found this guidance from the owner of CommandLineUtils, and he advised that "Split the command-line argument parser and application execution into separate class structures" to test various options programmatically. It is a great suggestion, and I rewrote my program by adding class CommandLineOptions and adding logic to the constructor of class Generator. I can kill two birds with one stone by this change: code refactoring and writing better tests.
Another problem I had was my folder structure. Before, I put the project's sln file, .git file , and src files in the root of the folder. However, when I added a new test project for Shinny-SSG, I had it outside my git folder, and it would be impossible to commit the change and put it in my remote repository. To resolve that, I had to change my folder structure to this:
C:.
├───shinny-ssg
│ ├───bin
│ │ ├───Debug
│ │ │ └───netcoreapp3.1
│ │ │ ├───dist
│ │ │ └───publish
│ │ ├───Destination
│ │ └───Release
│ │ └───netcoreapp3.1
│ ├───obj
│ │ ├───Debug
│ │ │ └───netcoreapp3.1
│ │ └───Release
│ │ └───netcoreapp3.1
│ ├───Properties
│ └───src
└───shinny-ssgTests
├───bin
│ └───Debug
│ ├───.netcoreapp,version=v3.1
│ └───netcoreapp3.1
├───obj
│ └───Debug
│ ├───.netcoreapp,version=v3.1
│ └───netcoreapp3.1
└───src
Testing
I wrote 3 test for Generator class run()
function that cover 3 different cases: config file option, input path option and invalid input path option. My tests help uncovering a huge bug in my application. Before, I thought that default
keyword was used to specified the default value of a variable.
cssUrl = cssOption.HasValue() ? cssOption.Value() : default;
However, the default
literal is for producing the default value of a type that is null in this case ( CssUrl is the string
type).
I also wrote a test that testes the core feature of my application: Given a text and checked if the generated HTML value matched the expected output.
Pull request
Throughout this experience, I learn a lot about software testing and why it is essential for software development. In the future, I will implement more tests for my project and explore other test frameworks.
Top comments (0)