Showing posts with label TDD. Show all posts
Showing posts with label TDD. Show all posts

Saturday, October 12, 2013

Integration testing approaches: Should we use in-memory database?

Integration testing is a form of testing that verifies that components of our application properly work together & with external resources(database, disk-drive etc).

Let's say we have application that uses database in some way. How can we cover components that use database by Integration tests?

The most important principle of testing is Isolation:

Tests should be isolated in the data creating and quering from other tests.

So, each good Integration test that uses database should consists of the following steps:
  • Cleaning database 
  • Inserting testing data 
  • Calling component being tested 
  • Checking result / database state 

There are 3 popular ways to write Integration Tests:
  1. Use the same development database for Integration tests 
  2. Generate empty database before each test 
  3. Use some in-memory database 
1. The first choice is to use the same development database for testing. This choice is the worst one, because we can't populate development database by testing data without breaking Isolation principle.

So, it's read-only mode testing. We can test some read-only requests to database, but even then, we are unable to make assertions well, because this data is fragile(we can make changes in our development database at any time and tests will be broken).

2. The second choice is to generate empty database with testing data before each test.
It's good practice to have testing environment that resembles real production environment as close as possible. So, in this case we use the same database-engine for testing as production's one, which makes possible to catch some database-specific problems early.

Disadvantage of this approach is that Integration tests can be pretty slow.

3. The third choice is a to use in-memory database.
If for some reasons we can't use the second choice then we can use in-memory database for testing. It's the compromise choice, because we can ensure Isolation of our tests + high speed of execution, but we sacrifice the closeness to the real environment.

Sqlite is a great example of such database.

For example, if we use NHibernate it's very easy to inject Sqlite database(instead of our real one) in our tests. This database will be based on the same NHibernate mappings and will use the same database-logic.

If you are interested in this approach, you can find example project of using NHibernate + Sqlite for testing on GitHub.

Sunday, September 1, 2013

JasmineJs integration with ReSharper & TeamCity


JasmineJs is a great framework for testing JavaScript code.

We'll discuss here how to integrate it with other amazing products: ReSharper 7 & TeamCity.

Download


You can download standalone example here(with additional files to run tests from ReSharper & TeamCity).

This package contains two folders: SpecRunner and YourWebSite. We’ll need them later.

JasmineJs + ReSharper 7 = Friends


To run client-side tests without dependency on your browser we can use PhantomJs WebKit.

Put files from downloaded SpecRunner folder somewhere in your solution.

For example, in my solution these files are located in MyProject/Testing/Client/ folder.

Now we can configure ReSharper to use PhantomJs:

Now we can create JS-files with tests, and run them directly from Visual Studio(thanks to ReSharper) without running our browser(thanks to PhantomJs):

You need to include necessary scripts(scripts to be tested + their dependencies) using reference syntax.
However, note that we don’t need to include JasmineJs scripts, because ReSharper has it’s own inside.


JasmineJs + TeamCity = Friends


Preparing project for running JS-tests from TeamCity 


Put downloaded YourWebSite/lib/ folder in Scripts/Jasmine/ folder of your Web project.

Put downloaded YourWebSite/SpecRunner.htm file in the root of your Web project.

For example:





















Then you need to configure SpecRunner.htm to include all necessary scripts:
  • JasmineJs scripts(ReSharper doesn’t need them, but TeamCity does); 
  • Source files to be tested + their dependencies; 
  • Spec files with tests; 
  • jasmine.teamcity_reporter.js 
Note, that we include jasmine.teamcity_reporter.js that is needed for integration with TeamCity.

Example of SpecRunner.htm:

Configuring TeamCity for running JS-tests from our project


We need to create additional Build Step in TeamCity:

Note, that we specify Working directory as Testing/Client/ folder of our solution(where we put downloaded files from SpecRunner folder).

Wednesday, July 3, 2013

Using Rhino Mocks after FakeItEasy experience

Recent years i always use FakeItEasy as my favorite mock framework. And i was very happy about it.

But few weeks ago i have joined team that uses Rhino Mocks. So, i've got a chance to compare them.

Both frameworks provide just about the same facilities, but i found FakeItEasy syntax more convenient to use. Plus, there is no difference between stub and mock in FakeItEasy- everything is just a fake! You don't need to remember which one to use. In Rhino Mocks i sometimes create stub, then later, decide to create expectations on it and then wonder: "Why my expectations are always pass?" Then i realize that i need to refactor my code to use mock instead of stub. There are no such problems in FakeItEasy.

Maybe it's a matter of habit, but my advice is to use FakeItEasy, it's much cooler. 

Tuesday, October 16, 2012

Testing ASP.NET MVC routes using NUnit and FakeItEasy

Let's say we have registered routes in our ASP.NET MVC application:
 routes.MapTrailingSlashRoute(  
   "Topic", // Route name  
   "news/{url}", // URL with parameters  
    new { controller = "Topic", action = "Index" } // Parameter defaults  
 );  
 
 routes.MapTrailingSlashRoute(  
   "Default", // Route name  
   "{controller}/{action}/{id}", // URL with parameters  
   new { controller = "Home", action = "Index" , id = "" } // Parameter defaults  
 );  

How can we test this routes using NUnit testing framework and FakeItEasy mocking framework?

Here's an example of how this can be done:
     [TestFixture]  
     [Category("Unit")]  
     public class when_using_registered_routes  
     {                    
       [TestFixtureSetUp]  
       public void Prepare()  
       {  
         MvcApplication.RegisterRoutes(RouteTable .Routes);   
       }  
       [Test]  
       [TestCase("~/", "Home", "Index" )]        
       [TestCase( "~/news/testing-routes-in-mvc/", "Topic" , "Index" )]  
       [TestCase("~/discussion/all/", "Discussion", "All")]        
       [TestCase( "~/discussion/widget/", "Discussion" , "Widget" )]  
       public void should_return_expected_controller_and_action(string path, string expectedController, string expectedAction)  
       {                  
         var httpContext = A.Fake<HttpContextBase>();          
         A.CallTo(() => httpContext.Request.AppRelativeCurrentExecutionFilePath).Returns(path);                  
         var routeData = RouteTable.Routes.GetRouteData(httpContext);  
         Assert.That(routeData.Values["controller"].ToString().ToLower(), Is.EqualTo(expectedController.ToLower()));  
         Assert.That(routeData.Values["action"].ToString().ToLower(), Is.EqualTo(expectedAction.ToLower()));  
       }       
     }