This is my second blog post. The first one wasn't successful, as it was broad but shallow. I aimed to establish a foundation and build upon it, but I felt like I fell into a state similar to analysis paralysis. I needed to release something to free up my mind and continue somehow. I admit it was too long; a few of my colleagues told me they clicked "like" but didn't read it because it was too lengthy. In this post, I will focus solely on the easyTdd tool, how it can help by generating test templates, and how it can be configured to suit your needs. I won't cover all the features in this blog post, just test generation, but with more depth. In my next blog post, I will cover method and class generation for test cases of parameterized tests, in a similar manner to how I discuss test generation today. As a reminder, EasyTdd is a Visual Studio extension that aids in test-driven development by generating test templates and other useful code blocks. It can be installed directly from the Visual Studio Extension Manager or downloaded from the Visual Studio Marketplace.
ReSharper
EasyTdd features are implemented using the Visual Studio Quick Action menu. ReSharper may override this menu and hide it. To enable it, navigate to ReSharper's options and uncheck "Hide Visual Studio Quick Action icons in the left editor margin":
Configuration
When a solution is opened, EasyTdd checks for the settings. If nothing is found, it generates an .easyTdd folder in the solution folder. Inside, it adds a default settings.json file and DefaultTemplates folder with collection of template files.
Each feature has its own section in the settings.json file, accompanied by one or more template files. Templates are written in the Scriban scripting language. All configurations are solution-specific and can be customized to fit particular project requirements. Feel free to make any necessary changes to the settings.json file. If changes are needed in a template, copy and paste it, then make the changes there. Don't forget to update the corresponding template name in the settings.json file. Default templates are updated with every release, so any changes made directly to them will be lost.
Test generation in details
Once EasyTdd is installed on Visual Studio and ReSharper is configured as mentioned above, invoking the Quick Actions menu on a class declaration will display the "Generate Test" action, as shown below:
Clicking on it, EasyTdd will generate a CalculatorTests class in the ClassLibrary.Tests project, similar to the following:
namespace ClassLibrary.Tests
{
public class CalculatorTests
{
private string _expression;
[SetUp]
public void Setup()
{
_expression = string.Empty;
}
[TestCase(null)]
public void CalculateThrowsArgumentExceptionWhenExpressionIsNotValid()
{
_expression = expression;
Action action = () => CallCalculate();
action
.Should()
.Throw<ArgumentException>();
}
private double CallCalculate()
{
var sut = Create();
return sut
.Calculate(
_expression
);
}
private Calculator Create()
{
return new Calculator();
}
}
}
Settings for test generation
The default placement, naming, and location of the generated test may not suit everyone's preferences and requirements. Fortunately, all of these aspects can be easily customized to better align with your needs and tastes. Now, I will provide settings one by one. Settings for test generation are located in settings.json
under the Test
field. Here are the descriptions:
ClassSuffix - default value is
Tests
. This value determines the suffix added to the class's corresponding test class name. In the previous example forCalculator
, it wasCalculatorTests
.NameInMenu - default value is
Test
. This minor setting enables you to modify the name displayed in the Quick Actions menu. By default, it will be "Generate Test", but you can rename it to whatever you prefer. For instance, using the value "Unit Test" will result in "Generate Unit Test" as the menu item.AssemblySpecificTargetProjectSuffix - default value is
Tests
. This setting instructs EasyTdd to place generated tests in the corresponding test project for each project. It will search for a project with the same name plus the predefined suffix. In the example above,Calculator
is in the projectClassLibrary
and the corresponding test project isClassLibrary.Tests
. This can be customized to suit individual preferences and requirements, such as prefixing the test project withUnitTests
or something else. Within the test project, EasyTdd maintains the original folder hierarchy.TargetProjectNameForAssembliesWithoutSpecificTargetProject - default value is
null
. This unusually long-named setting is used to specify a project name when it doesn't match the source project naming. For example, if I want to place all tests from all projects into a single test project calledClassLibrary.AllTests
, I would set this setting toClassLibrary.AllTests
. In this case, I can leave AssemblySpecificTargetProjectSuffix with its default value, as EasyTdd will first try to find a project with the predefined suffix and then fall back to the value in TargetProjectNameForAssembliesWithoutSpecificTargetProject if it doesn't find one. If EasyTdd doesn't locate the project specified in TargetProjectNameForAssembliesWithoutSpecificTargetProject, it will place the test class next to the class being tested.Folder - default value is
null
. For instance, if I choose to have a single project for all test-related components - including all tests, builders, test doubles, etc. - I might want to organize them in corresponding folders. If I set TargetProjectNameForAssembliesWithoutSpecificTargetProject toClassLibrary.AllTestStuff
and set Folder toTests
, then the test forClassLibrary\Services\SomeService.cs
will be placed inClassLibrary.AllTestStuff\Tests\Services\SomeServiceTests.cs
.DefaultTestFramework - the default value is
NUnit
. EasyTdd attempts to identify the testing framework used in the target test project. If it fails to recognize the framework, it will use templates for the test framework specified here.OutputSettings - this section contains configurations for
NUnit
,MsTest
, andxUnit
testing frameworks. Each configuration has the same structure, so I will provide an overview of the structure without focusing on a specific testing framework.FileTemplates - this section contains settings for the specific files that will be generated.
NameTemplate - default value is
{{className}}.cs
, whereclassName
refers to the name of the test class.ContentTemplateFile - The default value depends on the testing framework. For NUnit, the default is
nunit.test.tpl
. If you need to change the template, create a copy and then modify the template file name here.Recreate - default value is
false
. When a class already has a test file created, EasyTdd offers the options to "Open CalculatorTests.cs" and "Regenerate CalculatorTests.cs" instead of "Generate Test". In many cases, I don't want to regenerate the test file, so setting this value to false will hide the "Regenerate" options from the menu.
ToolingNamespaces - by default, this contains a list of namespaces to support the tooling used in the default test template. Examples include
Moq
,FluentAssertions
, and testing framework-specific namespaces. EasyTdd adds source class-related namespaces to the generated class, but it is not aware of the tooling used in the template itself. This is where you can define those namespaces.
Adapting the template
The default outcome, as seen in the Calculator
example above, may not suit everyone's preferences. You might want to adapt it to better fit your needs. For instance, fields are prefixed with an underscore, FluentAssertion is used, and the namespace declaration follows the .NET framework style with curly braces. So, what can you do about that? If your project uses NUnit
, for instance, copy .easyTdd/DefaultTemplates/nunit.test.tpl and paste it into a new location, such as .easyTdd/MyTemplates/nunit.test.tpl. Open the file with a text editor and make any necessary changes. The template is written in the Scriban scripting language. Please refer to the documentation for more information. As mentioned earlier, don't forget to update setting.json with the new template name. In this particular case, the Test.OutputSettings[NUnit].FileTemplates[0].ContentTemplateFile
value should be changed to "mytemplates\\nunit.test.tpl"
.
Messing up with configuration
Since there is no UI for the configuration yet, it's easy to make mistakes with it. A source control system like Git can be helpful in this situation, but if the configuration files haven't been committed yet, feel free to delete the .easyTdd folder. It will be recreated with default settings the next time the solution is opened.
What's next?
This is just the beginning. In upcoming blog posts, I will demonstrate how to generate test case methods and classes for parameterized tests, as well as create builders and mocks. There are still a few features I'm working on:
Adding dependencies and generating all necessary test code to start working with a dependency easily.
Renaming/moving dependent files when the source file is renamed/moved. For example, if Calculate.cs is renamed to Calculator.cs, I want CalculateTests.cs to be automatically renamed to CalculatorTests.cs. Similarly, if I move Calculator.cs to the Services folder, I want CalculatorTests.cs to be moved to the Services folder in the test project as well.
In conclusion
I hope this blog post has been helpful. I've introduced one feature of EasyTdd - test class template generation - and explained how to configure this feature to suit your needs. Please feel free to ask questions and provide feedback.