Saturday, October 4, 2014

Unit testing smells: The class constructor is not easy to call

When we want to test an instance method on a class the first challenge is to create an instance of that class. Hopefully the class constructor is easy to call but that's not always the case.

Let's review a few cases where the constructor might prevent us to write tests easily:
  • The constructor is private or internal
  • It requires too many arguments or it is too hard to create/provide those arguments
  • The constructor calls external dependencies

The case of the internal or private constructor

For this we can follow the same advices than with testing non-public class. But whatever you do please don't use reflection to call the constructor.

Also stated in testing non-public class, you should ask yourself if it would be better to test this class via another public class that use it. A private constructor usually means that there is a factory somewhere you should use to instantiate the class. You should figure out a way to use that factory or redesign it in case you have difficulties to work with it in unit tests.

When dealing with internal access modifier I usually use the InternalVisibleTo attribute for my test project.

[assembly: InternalsVisibleTo("Contoso.MyApp.UnitTests.dll")]

The case of the difficult constructor arguments

If the problem is that the constructor requires too many arguments then you should ask yourself if this class is too big, maybe it has too many responsibilities and don't follow the Single Responsibility Principle? In that case the class should be splitted into two or more classes. This way it will be easier to test the smaller class because its constructor should require less arguments.

Another case is when the arguments are difficult to create or provide. Maybe that in order to create one object to pass as parameter we need to create yet more objects. Micheal Feathers calls it the Onion Parameter in his book Working Effectively with Legacy Code. In that case I usually invest into a bit of testing infrastructure like factory methods or Test Data Builder in order to help me write tests faster afterwards.

Finally some parameters could be classes that wrap services or external dependencies. In that case I abstract the dependency using an interface and the Inversion of Control Principle. First extract an interface from the class. Next change the constructor to use this interface instead of the class. Finally use a mocking framework like Moq to create a fake (or create your own by hand if you don't like mocking frameworks) and pass it to the constructor.

public class MyService
{
    // public MyService(SomeDataAccessLayer dal, SomeExternalService externalService)
    public MyService(ISomeDataAccessLayer dal, ISomeExternalService externalService)
    {
        // ...
    }

    // ...
}

The case of the external dependencies calls

When the constructor itself calls an external dependency I usually refactor the constructor to inject this dependency via a parameter instead, this is called dependency injection and usually comes with the Inversion of Control Principle. This is also a good occasion to take a look at a IoC Container like Unity.

public class MyService
{
    // public MyService()
    public MyService(ISomeExternalService externalService)
    {
        // ...
        // var externalService = new ExternalService();
        externalService.CallService();
    }

    // ...
}

Saturday, September 6, 2014

Unit test smells: The non-public class

Writing unit tests for a method on a class that is not public is doable but not straight forward. It could be done using a bit of reflection like this

var type = Type.GetType("MyProject.MyClass");
var methodInfo = type.GetMethod("TheMethod");

var classInstance = Activator.CreateInstance(type, null);
methodInfo.Invoke(classInstance, null);

That is quite a bit of work. Of course you could create some test infrastructure to avoid duplication in every tests or you may find libraries online for that. But still, writing tests like this smells funny to me.

In short, you should never write tests directly against a non-public class.
Let's take a look at the 2 possible cases for this: the private class and the internal class.

The case of the private class

For a class to be private means it is nested inside another class

public class A
{
    // ...

    private class B
    {
        // ...
    }
}

In a situation like this class B can only be used by class A. Anything class B do is only for serving class A. If you want to test a method in class B you should find out how class A use class B and write your tests against class A public API.

If you find there is no way to reach the method you want to test in class B through class A it simply means that you just found dead code! If you found a way but find it too hard to setup a test then maybe class B is not simply a private utility class. In that case I would extract class B from inside class A and change its access modifier to internal. Unfortunately, now any class inside the same assembly could use class B. It is a trade-off I'm willing to pay because this case is really rare and C# still lack a proper access modifier scoped to the current namespace.

The case of the internal class

Internal class could also be tested through reflection. Personally I prefer to use the InternalsVisibleToAttribute and give access to internals types to my unit test project. To do it you need to add the attribute to the project under test AssemblyInfo.cs file like this

[assembly: InternalsVisibleTo("Contoso.MyApp.UnitTests.dll")]

If your project is signed you will need to also provide the assembly's public key like this

[assembly: InternalsVisibleTo("Contoso.MyApp.UnitTests.dll, PublicKey=1234...789")]

Again, this is a trade-off: you give special access to your internal types only for testing but it is way better than changing the class access modifier to public. You should never change a type access modifier to public for testing!

Conclusion

I always try to write tests against public classes and methods. Sometime an internal class will grow to be very complex over time and become its own new component. In a solution were we create a lot of small projects we would simply create a new one for such component and expose it publicly but that is not what I do. I usually try to create the minimal number of projects in my solution so testing internal classes using the InternalsVisibleToAttribute is a good trade-off for me.

Sunday, July 13, 2014

Exploring BDDfy

BDDfy is a BDD library (part of the larger TestStack project). It's function is to turn regular unit tests to BDD style tests (using the Gherkin syntax). You can read more about BDDfy here.

BDDfy can be used with any test framework or runner.

Acquiring

To add BDDfy to your test project via NuGet run this command in the Package Manage Console.

Install-Package TestStack.BDDfy

Optionally, you can also install code samples with this package.

Install-Package TestStack.BDDfy.Samples

Exploring


Hello world

For this part I'll be using the xUnit test framework. Let's start with something simple.

public class FirstTest
{
    void GivenTwoAndTwo()
    {
        // ...
    }

    void WhenIAddThem()
    {
        // ...
    }

    void ThenTheAnwserShouldBe4()
    {
        // ...
    }

    [Fact]
    public void ExecuteFirstTest()
    {
        this.BDDfy();
    }
}

All the magic is done by the BDDFy extension methods. This will scan the FirstTest class for methods starting with keywords like Given, When and Then. Next, it will run the methods in order (BDD style). Finally, we will get a nice output report like this.

Test output in Visual Studio

BDDfy will also generate a BDDfy.html file in the test project output folder. This is the report of all BDDFyed tests.

HTML tests report

Using attributes to customize the test

BDDfy follow conventions when scanning a class for methods of interest, you can find a list here. If we need more control we can do it by using attributes.

[Story(
    AsA = "As someone lazy",
    IWant = "I want the computer to add 2 number",
    SoThat = "I don't have to do the math myself")]
public class TestWithAttributesToOverriteText
{
    [Given("Given 2 + 2")]
    void GivenTwoAndTwo()
    {
        // ...
    }

    [When(" + ")]
    void WhenIAddThem()
    {
        // ...
    }

    [Then("Then the anwser = 4")]
    void ThenTheAnwserShouldBe4()
    {
        // ...
    }

    void AndThenItShouldDisplayTheAnwser()
    {
    }

    [Fact]
    public void ExecuteTestWithAttributes()
    {
        this.BDDfy();
    }
}

First, the [Story] attribute allow us to provide the classic story definition for the test. Other attributes like [Given], [When] and [Then] allow us to provide a custom description for the steps. Also, using the attributes will allow us to name the step methods the way we want.

Creating more than one scenario per story

Usually a story contains more than one test or scenario. We can do this using nested classes.

[Story(
    Title = "Using story attribute and setting the Title!",
    AsA = "As someone learning BDDfy",
    IWant = "I want to try splitting scenario in separated classes",
    SoThat = "My code is cleaner")]
public class TestWithStoryAndScenarioInSeparatedClasses
{
    [Fact]
    public void FirstScenario()
    {
        new S1().BDDfy("Custom scenario title");
    }

    [Fact]
    public void SecondScenario()
    {
        new S2().BDDfy();
    }

    private class S1
    {
        void GivenWhatever() { // ... }
        void WhenSomethingHappens() { // ... }
        void ThenProfit() { // ... }
    }
    private class S2
    {
        void GivenWhatever() { // ... }
        void WhenSomethingElseHappens() { // ... }
        void ThenProfit() { // ... }
    }
}

This will group scenarios together in the output report.

Using the fluent API for even more control

With what we've seen previously we need to create a new test class for each scenario we have. That leads to a lot of duplicated code unless we delegate to a common test fixture. An alternative is to use BDDfy fluent API to get some code reuse between our scenarios.

public class TestWithFluentApi
{
    [Fact]
    public void ReusingStepForScenario1()
    {
        new TestWithFluentApi()
            .Given(s => s.GivenWhatever(), "Given some pre-condition")
                .And(s => s.AndOtherGiven(54))
            .When(s => s.WhenSomethingElseHappens())
            .Then(s => s.ThenProfit())
                .And(s => s.AndManyMore(45))
            .BDDfy();
    }

    [Fact]
    public void ReusingStepForScenario2()
    {
        new TestWithFluentApi()
            .Given(s => s.GivenWhatever(), "Given some pre-condition")
                .And(s => s.AndOtherGiven(123))
            .When(s => s.WhenSomethingElseHappens())
            .Then(s => s.ThenProfit())
                .And(s => s.AndManyMore(321), "And {0} more things!")
            .BDDfy("Scenario 2 with steps re-use");
    }

    void GivenWhatever() { // ... }
    void AndOtherGiven(int input) { // ... }
    void WhenSomethingElseHappens() { // ... }
    void ThenProfit() { // ... }
    void AndManyMore(int expected) { // ... }
}

With this style of test, not only we can reuse steps between scenarios we also gain the ability to parameterize the steps.

Assessment

I've only scratched the surface of what BDDfy can do. You can read more about on BDDfy usage and customization on the project web site.

In the past I've use SpecFlow for my BDD tests. With SpecFlow you write your specification in a text file using the Gherkin language. The tool then parse the file and execute corresponding method for each steps. Having a text file seems interesting because we could have a business analyst write those. In really, developers ends up writing the stories and scenarios anyway.

This is why I like BDDfy, it's easy to learn and gives developers a lot of control over the way we create BDD style tests.

One more for my toolbox!

I hope you enjoyed this introduction to BDDfy.

Sunday, June 22, 2014

Visualizing Nuget packages dependencies without Visual Studio Ultimate

In my previous post I've shown the Package Visualizer tool. Unfortunately, it's only available in the Ultimate version of Visual Studio. But all is not lost because even with a Pro version with can open DGML files.

I've created a LinqPad query that analyse packages.config files and create a DGML diagram like Package Visualizer does. I've also added things like GAC libraries and normal file based library to the mix. You can get the full Gist here. Now let's take a look at some code…

Main

Here we set a few options for our query: some file extensions to ignore when scanning for projects and more importantly the root folder path to start scanning for project files.

private string[] projectExtensionExclusions = new[] { ".vdproj", ".ndproj" };
private string rootFolder = @"C:\Users\Pascal\Dev\MyProject";

void Main()
{
  LoadAllProjects();
  LoadAllPackagesConfig();
  GenerateDGML(Path.Combine(rootFolder, "Dependencies.dgml"));
}

Data structures to uses

Then we define some fields and basic classes to help us gather the information

private List<Project> projects = new List<Project>();
private List<Package> packages = new List<Package>();
private List<Library> libraries = new List<Library>();

public class Project
{
  public Project()
  {
    this.Projects = new List<Project>();
    this.Libraries = new List<Library>();
    this.Packages = new List<Package>();
  }
  public string Path { get; set; }
  public string Name { get; set; }
  public List<Project> Projects { get; private set; }
  public List<Library> Libraries { get; private set; }
  public List<Package> Packages { get; private set; }
}

public class Package
{
  public string Name { get; set; }
  public string Version { get; set; }
}

public class Library
{
  public string Name { get; set; }
  public bool IsGAC { get; set; }
}

LoadAllProjects

Now we can start scanning for projects to load. Next we open each project files and extract all dependencies like other project, a local library or a GAC reference. We keep all this info in the project instances for later.

private void LoadAllProjects()
{
  XNamespace ns = "http://schemas.microsoft.com/developer/msbuild/2003";
 
  var projectFiles = Directory.GetFiles(rootFolder, "*.*proj", 
    SearchOption.AllDirectories)
    .Where (pf => !projectExtensionExclusions.Any(ex => pf.EndsWith(ex)));
 
  foreach (var pf in projectFiles)
    this.projects.Add(
      new Project { Path = pf, Name = Path.GetFileNameWithoutExtension(pf) });

  // Get all projects, local libraries and GAC references
  foreach (var project in this.projects)
  {
    var projectDoc = XDocument.Load(project.Path);

    foreach (var pr in projectDoc.Descendants(ns + "ProjectReference"))
    {
      var prj = projects.SingleOrDefault(p => 
        p.Name == pr.Element(ns + "Name").Value);
      if (prj != null) 
        project.Projects.Add(prj);
      else
        (pr.Element(ns + "Name").Value 
          + " project reference not found in file " + project.Path).Dump();
    }

    foreach (var r in projectDoc.Descendants(ns + "Reference")
      .Where (r => !r.Value.Contains(@"\packages\")))
      project.Libraries.Add(GetOrCreateLibrary(
        r.Attribute("Include").Value, !r.Elements(ns + "HintPath").Any()));
  }
}

LoadAllPackagesConfig

Finally we scan for packages.config files, the ones responsible for maintaining the NuGet packages dependencies for a project. Again we extract the dependencies information from the files and keep it for later.

private void LoadAllPackagesConfig()
{
  foreach (var pk in Directory.GetFiles(rootFolder, "packages.config",
    SearchOption.AllDirectories)
    .Where (pc => !pc.Contains(".nuget")))
  {
    var project = this.projects.SingleOrDefault(p =>
      Path.GetDirectoryName(p.Path) == Path.GetDirectoryName(pk));
    if (project == null)
      ("Project not found in same folder than package " + pk).Dump();
    else
    {
      foreach (var pr in XDocument.Load(pk).Descendants("package"))
      {
        var package = GetOrCreatePackage(
          pr.Attribute("id").Value, pr.Attribute("version").Value);
        project.Packages.Add(package);
      }
    }
  }
}

GenerateDGML

Here we generate the final DGML file which is simply an XML file. The schema is quite simple: a root element DirectedGraph, a Nodes section and a Links section, all of which are mandatory. We also add a Styles section to colorize the different kind of nodes: projects, packages, libraries and GAC libraries.

private XNamespace dgmlns = "http://schemas.microsoft.com/vs/2009/dgml";

private void GenerateDGML(string filename)
{
  var graph = new XElement(dgmlns + "DirectedGraph", 
    new XAttribute("GraphDirection", "LeftToRight"),
    new XElement(dgmlns + "Nodes",
      this.projects.Select (p => CreateNode(p.Name, "Project")),
      this.libraries.Select (l => CreateNode(l.Name, 
        l.IsGAC ? "GAC Library" : "Library", l.Name.Split(',')[0])),
      this.packages.Select (p => CreateNode(p.Name + " " + p.Version, "Package")),
      CreateNode("AllProjects", "Project", label: "All Projects", @group: "Expanded"),
      CreateNode("AllPackages", "Package", label: "All Packages", @group: "Expanded"),
      CreateNode("LocalLibraries", "Library", label: "Local Libraries", @group: "Expanded"),
      CreateNode("GlobalAssemblyCache", "GAC Library", label: "Global Assembly Cache", @group: "Collapsed")),
    new XElement(dgmlns + "Links",
      this.projects.SelectMany(p => p.Projects.Select(pr => new { Source = p, Target = pr } ))
        .Select (l => CreateLink(l.Source.Name, l.Target.Name, "Project Reference")),
      this.projects.SelectMany(p => p.Libraries.Select(l => new { Source = p, Target = l } ))
        .Select (l => CreateLink(l.Source.Name, l.Target.Name, "Library Reference")),
      this.projects.SelectMany(p => p.Packages.Select(pa => new { Source = p, Target = pa } ))
        .Select (l => CreateLink(l.Source.Name, l.Target.Name + " " + l.Target.Version, "Installed Package")),
      this.projects.Select (p => CreateLink("AllProjects", p.Name, "Contains")),
      this.packages.Select (p => CreateLink("AllPackages", p.Name + " " + p.Version, "Contains")),
      this.libraries.Where (l => !l.IsGAC).Select (l => CreateLink("LocalLibraries", l.Name, "Contains")),
      this.libraries.Where (l => l.IsGAC).Select (l => CreateLink("GlobalAssemblyCache", l.Name, "Contains"))),
    // No need to declare Categories, auto generated
    new XElement(dgmlns + "Styles",
      CreateStyle("Project", "Blue"),
      CreateStyle("Package", "Purple"),
      CreateStyle("Library", "Green"),
      CreateStyle("GAC Library", "LightGreen")));

  var doc = new XDocument(graph);
  doc.Save(filename);
}

Conclusion

All that is left is to open the Dependencies.dgml file in Visual Studio


I've left a few utility methods out of the inline code in this post but you can get all the code from the Gist. Feel free to grab a copy of the file and adapt it to your heart's content. It would be easy to create a small Console Application and call it from command line if you don't like LinqPad.

There is still a lot more I could add to the query like extracting projects and library versions from the DLL, dependencies between NuGet packages from .nupkg files and highlighting duplicates NuGet packages with different version. Still, it's enough for me in it's current form.

I hope this will help you figure out your NuGet packages usage and dependencies in your solution.

Saturday, May 24, 2014

Managing NuGet packages dependencies with the Package Visualizer tool

If you ever used NuGet on a large enough solution you know you can get into trouble when projects reference different versions of the same NuGet package. That happens a lot in Azure projects as the libraries/packages get updated all the time.

I'm really surprise when I talk to people using NuGet everyday that they don't know about the Package Visualizer tool. (update: I've been told that this feature requires VS Ultimate and is not available in the Pro version. I'm still going to show it to you but stay tune for another post with a free alternative later)

NuGet Package Visualizer in Visual Studio


Once you open up a solution in Visual Studio you can go to the Tools menu, NuGet Package Manager and Package Visualizer.


This will analyse all the packages.config files in the solution and generate a DGML diagram of all NuGet packages and projects of the solution.  The diagram will help us see packages usage in the solution and find the ones with different versions.  Below you can see that I've tried this on the Roslyn (open source C# compiler) solution.


The first thing to note (and a surprise to me!) is that Roslyn use the XUnit testing framework and not MsUnit! More seriously we can quickly see that we have no duplicate packages with different versions. If we compare that to this sample solution I created we can see I'm using two versions of the Json.NET library. Now I know I should update the ClassLibrary1 project to use the new version of the package.


Of course, this only work for NuGet packages but it would be useful to have something like this for regular DLL references.  I'll try to work on a LinqPad query to generate such a DGML graph with all projects, libraries and packages.  Stay tune till next time.

Friday, April 25, 2014

Looking inside a NuGet package with NuGet Package Explorer

When I really want to learn something new (like a new tool, technology or a programming language) I do two things

  • I try it myself
  • Check out what others have done

I'm currently learning how to create my own NuGet packages so I'm trying to do a lot of things on my own, but I would also like to see how existing packages are made.

After installing a NuGet package in your project you can go in the packages folder and unzip the .nupkg file (yes, it's only a zip file with a different extension).  Fortunately, there is an easier. NuGet Package Explorer is an open source tool available on CodePlex.

With it you can load a package from the official NuGet feed or any other feeds you want even local feeds.


Then when we open a package we can explore its content and even go inside individual files



NuGet Package Explorer also allow us to edit files and the package itself if we want.

One trick I like to do is to add my local NuGet package download cache as a feed. To do that in the Tools menu select View NuGet download cache.



This is the folder where all the packages you previously downloaded are cached (from Visual Studio, NuGet Package Explorer and any other NuGet based tools). Simply copy the path and paste it in the Package Source field like this



This way I can quickly get to a package I just installed in my solution.

NuGet Package Explorer is a powerful tool I use a lot to understand how NuGet packages are made.

I hope it will help you too.

Friday, April 18, 2014

Packaging and distributing tools using NuGet

NuGet is an amazing tool to manage dependencies for external libraries. As part of Visual Studio it gives us an easy way to install and update those libraries over time. Now even Microsoft use it extensively to release updates to us. But the power of NuGet doesn't stop here. Some people found imaginative ways to use NuGet like the ScriptCs project and Chocolatey.

Another usage is to package and distribute utilities via NuGet packages like FAKE and xUnit.Runners. To create your own tool package you need to author a NuSpec file like this:

<package>
  …

  <files>
    <file src="tooling\app.exe" target="tools\" />
  </files>
</package>

The key here is to set all your file's target to tools\. Doing that the package will be considered a solution-level NuGet package and will be available solution wide instead of only for one project.

For example if I install the xUnit.Runners package to my solution like this:

PM> Install-Package xunit.runners

You will see that only a new package.config file will be created in the .nuget folder at the root of your solution. This is where all solution-level packages will be referenced. Nothing will actually change inside your projects.

After that all the files required to run the xUnit runner from the command line, PowerShell or a build script will be available from the \packages\xunit.runners.1.9.2\tools folder.

The power of NuGet doesn't stop there but we'll check that in another blog post.