DEV Community

Kazys
Kazys

Posted on • Originally published at easytdd.dev

EasyTdd Quick Start: A Short and Simple Introduction

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":

Image description

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();
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

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 for Calculator, it was CalculatorTests.

  • 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 project ClassLibrary and the corresponding test project is ClassLibrary.Tests. This can be customized to suit individual preferences and requirements, such as prefixing the test project with UnitTests 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 called ClassLibrary.AllTests, I would set this setting to ClassLibrary.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 to ClassLibrary.AllTestStuff and set Folder to Tests, then the test for ClassLibrary\Services\SomeService.cs will be placed in ClassLibrary.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, and xUnit 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, where className 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.

Top comments (0)