Showing posts with label AutoFixture. Show all posts
Showing posts with label AutoFixture. Show all posts

Sunday, September 1, 2013

From Fact to Theory

I often find that the tests I write can be slowly generalized as the feature I happen to be working on is fleshed out. In xUnit.net terms I find that a fair number of the tests tend to move through these four stages:
  1. Start out as a single [Fact], working on hardcoded input data
  2. Pull out the hardcoded data, turning the tests into a [Theory, AutoData]
  3. Add edge cases, evolving the test into [Theory, AutoData, InlineData, InlineData]
  4. Add cases representative of equivalence classes, thus adding more InlineData attributes to the test
Each of the stages generalizes the test a bit more making it more potent in several ways. As the test moves through each stage it gains greater coverage in terms of the possible inputs, making it a better regression guard. But there is more at play. Along with the generalization (and multiplication) of the inputs the test can often be refactored towards being more about the behavior of the SUT and less about its implementation. So alongside the four stages above I find tests tend to move through these stages as well:
  1. While being a [Fact] the test is named something very specific - a specific example of how the SUT should behave
  2. During stage 2 or 3 the test name becomes something that expresses a general trait of the SUT
  3. The assertions in the test becomes less dependent on implemntation details
I am not always able to make my tests follow either of these progressions, but when I am I find it very rewarding.

Friday, August 24, 2012

Draupner: Full Stack ASP.NET MVC Scaffolding


A little while back I announced on twitter that Mjølner had open sourced it's ASP.NET MVC scaffolding tool, Draupner:



Since then Draupner has been updated to produce ASP.NET MVC 4 apps, and all the dependencies have been updated too. So now since like a good time an introductory post about Draupner.


Why Did we Build Draupner?
Scaffolding is not a new concept. It's been used for while in other web frameworks, and moreover Steven Sandersons ASP.NET MVC scaffolding has been around for a while too. That begs the question why another scaffolder? Basically because the existing ASP.NET MVC one does not do what we (Mjølner) want the way we want it: We want a simple command line tool that can

  • Set up a new ASP.NET MVC solution with a "Web" project along with an associated "Core" project and a "Test" project.
  • Add further entities to the solution as needed throughout the solutions lifetime
  • Add CRUD operations and GUIs to existing entities
  • Add tests for all the other stuff it adds
  • Allow us to code away happily on the solution without having to think about making the scaffolding tool happy

Furthermore, and importantly, we wanted everything the tool produced to follow an architecture we've used successfully time and again. This means setting up a certain structure in terms of projects and folders, as well as building on a certain technology stack that we like to work with. In other words the tool, Draupner, is a set of practices we at Mjølner have had succes with put into code. These last bits are what sets Draupner apart.

What Technology Stack does Draupner Set Up?
Draupner projects uses a bunch of technologies, that we've found to work well together. All of them are set up as NuGet dependencies (except Rake). The stack includes:


You can see the full list on the Draupner page on Github.

What Does a Draupner Solution Look Like?
Let's have a quick glance at a solution built with Draupner. This screenshot shows which projects such a solution consists of:



The .Web project is the ASP.NET MVC site: It includes views and some thin controllers, that rather quickly call into the .Core project.

The .Core project is where the domain model goes and where the persistence of said domain model is handled. We like intelligent domain models, so this is where the smarts of the application is meant to go.

The .Test project contains xUnit tests for both the .Web and the .Core projects.

This is all set up by Draupner during the initial project creation. Moving on from there Draupner can add further entities to the domain model and add CRUD operations/GUIs to those enitites. Taking a look inside the .Core project we see:



This gives a peek into the technolgoy stack used by Draupner projects: Entities are persisted to a SQL Server database via NHibernate (you can reconfigure NHibernate all you want if you e.g. want to change to MySql), and the NHibernate mappings are set up with Fluent.NHibernate. Draupner also create repositories for the enities it creates which the the controllers in the .Web project can use.

Also notice the Castle.Windsor dependency: All the code produced by Draupner uses dependency injection and inversion of control.Caslte.Windows is the IoC/DI container of choice used by Draupner proejcts. E.g. the repositories mentioned above expect an IUnitOfWork into which it can enroll operations. This is injected into them by Windsor. Skipping ahead a bit let me mention that the .Web project sets up an NHibernate unit of work per web request and registers it with Windsor.

Lastly we can notice that Draupner sets up Log4Net, so that it's ready to go.

Let's move up the stack and open up the .Web project:



We can see that Draupner has created controllers for the enities it created. These each allow for simple CRUD operations.

Draupner has also created simple, but nice Ajaxy CRUD views for the entities. Neither of these are really expected to be used in production, but act as placeholders until "the real thing" is implemented.

Draupner has also created a few view models, which are used in the CRUD GUIs and has set up Automapper configurations to map between the view models and the enitites in .Core.

Worth mentioning is also that the .Web project uses Elmah for error logging in the web layer.

As mentioned Draupner creates tests for all this as well. They end up the .Test project:

The tests are xUnit tests and use AutoFixture and Rhino.Mocks.

So What Now?
If this caught you're interest go clone the Draunper sample project on Github and take a harder look at how things are set up or take Draupner for a spin, following the instructions in the readme. If you like it, but find something missing or not working let us know. We're not making any promises with regards to support and bug fixes though, so an even better idea is to send a pull request. Those we do welcome.

Tuesday, September 6, 2011

Tip for making AutoFixture and xUnit.net play nice

Just a quick tip, for making AutoFixture 2.1 play nice with newer xUnit.net versions:

I installed Autofixture via NuGet, which gave me AutoFixture 2.1 and xUnit 1.7, when running my tests they threw this:

System.IO.FileNotFoundException: 
   Could not load file or assembly 
   'Ploeh.AutoFixture, Version=2.1.0.1, Culture=neutral,
   PublicKeyToken=b24654c590009d4f' 
   or one of its dependencies. 
The system cannot find the file specified.


The reason is that the test runner thinks that AutoFixture needs and older version of xUnit (although it doesn't really).
The solution is to put this in the app.config for the test projects:


    1   <runtime>
    2     <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    3       <dependentAssembly>
    4         <assemblyIdentity name="xunit.extensions"
    5                           publicKeyToken="8d05b1bb7a6fdb6c"
    6                           culture="neutral"/>
    7         <bindingRedirect oldVersion="1.6.1.1521"
    8                          newVersion="1.7.0.1540"/>
    9       </dependentAssembly>
   10     </assemblyBinding>
   11   </runtime>
   12 

You'll probably have to fix up the newVersion to the exact version you have.

That's it for now.