Showing posts with label Unit Testing. Show all posts
Showing posts with label Unit Testing. Show all posts

Sunday, February 26, 2017

Run .NET Core xUnit tests from ReSharper in VS2015

Visual Studio 2017 is literally only a few days away from release; so it might be a little late, but I finally figured out how to run .NET Core xUnit tests from ReSharper in VS2015! Good News: If you can't upgrade to VS2017 right away, then at least you can still run your unit tests!

Just make sure that the following is included in your project.json file (with the appropriate runtime):

{
  "testRunner": "xunit",
 
  "dependencies": {
    "dotnet-test-xunit": "2.2.0-preview2-build1029",
    "xunit": "2.2.0"
  },
 
  "frameworks": {
    "netcoreapp1.0": {
      "imports": "dnxcore50"
    }
  },
 
  "runtimes": {
    "win10-x64": {}
  }
}

Enjoy,
Tom

Sunday, April 24, 2016

How to Order xUnit Tests and Collections

xUnit is an extremely extensible unit testing framework!

If you need to control the order of your unit tests, then all you have to do is implement an ITestCaseOrderer. Once implemented, you just add a TestCaseOrdererAttribute to the top of your test class to use it. Below we use a custom OrderAttribute to order the tests.

To control the order of the test collections you can do a very similar trick by implementing an ITestCollectionOrderer. However, an ITestCollection is not neccessarily associated with a specific class, so to to use attributes to order them you need to use a little reflection. Check out the sample below for details.

Implementation

/// <summary>
/// Used by CustomOrderer
/// </summary>
public class OrderAttribute : Attribute
{
    public int I { get; }
 
    public OrderAttribute(int i)
    {
        I = i;
    }
}
 
/// <summary>
/// Custom xUnit test collection orderer that uses the OrderAttribute
/// </summary>
public class CustomTestCollectionOrderer : ITestCollectionOrderer
{
    public const string TypeName = "xUnitCustom.CustomTestCollectionOrderer";
 
    public const string AssembyName = "xUnitCustom";
 
    public IEnumerable<ITestCollection> OrderTestCollections(
        IEnumerable<ITestCollection> testCollections)
    {
        return testCollections.OrderBy(GetOrder);
    }
 
    /// <summary>
    /// Test collections are not bound to a specific class, however they
    /// are named by default with the type name as a suffix. We try to
    /// get the class name from the DisplayName and then use reflection to
    /// find the class and OrderAttribute.
    /// </summary>
    private static int GetOrder(
        ITestCollection testCollection)
    {
        var i = testCollection.DisplayName.LastIndexOf(' ');
        if (i <= -1)
            return 0;
 
        var className = testCollection.DisplayName.Substring(i + 1);
        var type = Type.GetType(className);
        if (type == null)
            return 0;
 
        var attr = type.GetCustomAttribute<OrderAttribute>();
        return attr?.I ?? 0;
    }
}

Thursday, March 31, 2016

xUnit.net: Extensions Config v3.3.0

I recently made several updates to the xunit.extensions.config library, which allows you to configure theory data from your app.config file. Here are the links to the source and the NuGet package:

New Features

  • Named Parameter Support

You no longer need to configure your data by parameter index. You can now name your data for each parameter, making the configuration much easier to read and understand.

  • AppSettings Support

You can now use the standard AppSettings section of the App.config to configure your data. If no settings are found, then the framework will fallback to trying to use the standard config section.

  • Default Namespace Option

You can now provide a default namespace for your tests. This reduced the amount of redundant text in your config file, and makes test names much more concise and easy to read.

  • Extensible Data Provider

Don't want to use the existing data providers? Would you rather use a database? Now you can! Just add an AppSettings key for "TestData.ServiceFactory" that provides the fully qualified name of a static method that returns an IConfigTestDataService, and the framework will try to use that to load configuration data.

Saturday, May 23, 2015

How To Capture Test Output in xUnit 2.0

As of xUnit 2.0 the test framework no longer captures any native outputs, this is by design. Now the question is: where do you write your test output?

You now have to write all test output to an interface, ITestOutputHelper, that is injected into your test's constructor. This design seems to have polarized developers a bit, as not everyone enjoys being require to add a constructor to your test classes. Personally, as a huge fan of dependency injection, I really like this solution.

Spoilers: My next blog post will be about how to combine this with Common.Logging and NLog.

Sample Test

using System.Threading.Tasks;
using Xunit;
using Xunit.Abstractions;
 
namespace XUnitDemo
{
    public class OutputTests
    {
        private readonly ITestOutputHelper _testOutput;
 
        public OutputTests(ITestOutputHelper testOutput)
        {
            _testOutput = testOutput;
        }
 
        [Fact]
        public async Task WriteLine()
        {
            _testOutput.WriteLine("Hello");
            _testOutput.WriteLine("World");
 
            await Task.Delay(1000);
            
            _testOutput.WriteLine("Goodnight");
            _testOutput.WriteLine("Moon");
        }
    }
}

Enjoy,
Tom

Thursday, April 9, 2015

xUnit.net: Extensions Config v2.0

Last year I open sourced some code that allowed you to power your xUnit theories from a custom section in your application configuration file. I have now updated that project to support xUnit 2.0, and also to allow for an optional name attribute to be set on each data set.

<testData>
  <tests>
    <add name="SampleProject.Class1.Main">
      <data>
        <add index="0" name="Optional" p0="Hello" p1="World" />
        <add index="1" name="Cows" p0="Goodnight" p1="Moon" />
      </data>
    </add>
  </tests>
</testData>

Enjoy,
Tom

Sunday, September 28, 2014

xUnit Theory Data from Configuration

I've said it before and I'll say it again, I love xUnit!

In particular, I love xUnits support for data driven tests. It offers several different options for ways to power a data driven unit test right out of the box. Best of all, xUnit allows for easy extensibility.

I have written some simple extensions for xUnit that allow you to power your data driven tests from your configuration file. Not only that, but it allows you to optionally provide default data using inline attributes when no configuration is available.

Sample Config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="testData" 
type="Xunit.Extensions.Configuration.TestDataSection,xunit.extensions.config"/>
  </configSections>
  <testData>
    <tests>
      <add name="Demo.Tests.Basic">
        <data>
          <add index="0" p0="1" />
        </data>
      </add>
      <add name="Demo.Tests.FromConfig">
        <data>
          <add index="0" p0="4" />
        </data>
      </add>
    </tests>
  </testData>
</configuration>

Sample Tests

namespace Demo
{
    public class Tests
    {
        [Theory]
        [ConfigData]
        public void Basic(int i)
        {
            // This theory data comes from the config file.
            Assert.Equal(1, i);
        }
 
        [Theory]
        [ConfigOrInlineData(2)]
        public void FromInline(int i)
        {
            // This theory data comes from the attribute.
            Assert.Equal(2, i);
        }
 
        [Theory]
        [ConfigOrInlineData(3)]
        public void FromConfig(int i)
        {
            // This theory data comes from the config file
            // instead of the attribute.
            Assert.Equal(4, i);
        }
    }
}

Enjoy,
Tom

Sunday, August 24, 2014

xUnit Console Runner - Filter by Test Name

You can now filter by test name with the xUnit Console Runner.

Sample Code

namespace DemoProject
{
    public class ExampleTests
    {
        [Fact]
        public void HelloWorld()
        {
            Assert.True(true);
        }
 
        [Fact]
        public void GoodnightMoon()
        {
            Assert.True(false);
        }
    }
}

Sample Command Line

C:\>xunit.console.exe DemoProject.dll -testName "DemoProject.ExampleTests.HelloWorld"
xUnit.net console test runner (64-bit .NET 4.0.30319.18449)
Copyright (C) 2014 Outercurve Foundation.

Starting:  DemoProject.dll
Finished: DemoProject.dll

=== TEST EXECUTION SUMMARY ===
   DemoProject.dll  Total: 1, Failed: 0, Skipped: 0, Time: 0.276s, Errors: 0

Enjoy,
Tom

Sunday, July 13, 2014

Use RavenDB to power Data Driven xUnit Theories

I love xUnit's data driven unit tests, I also really enjoy working with RavenDB, and now I can use them together!

Data driven unit tests are very powerful tools that allow you to execute the same test code against multiple data sets. Testing frameworks such as xUnit makes this extremely easy to develop by offering an out of the box set attributes to quickly and easily annotate your test methods with dynamic data sources.

Below is some simple code that adds a RavenDataAttribute to xUnit. This attribute will pull arguments from a document database and pass them into your unit test, using the fully qualified method name as a key.

Example Unit Tests

public class RavenDataTests
{
    [Theory]
    [RavenData]
    public void PrimitiveArgs(int number, bool isDivisibleBytwo)
    {
        var remainder = number % 2;
        Assert.Equal(isDivisibleBytwo, remainder == 0);
    }
 
    [Theory]
    [RavenData]
    public void ComplexArgs(ComplexArgsModel model)
    {
        var remainder = model.Number % 2;
        Assert.Equal(model.IsDivisibleByTwo, remainder == 0);
    }
 
    [Fact(Skip = "Only run once for setup")]
    public void Setup()
    {
        var type = typeof(RavenDataTests);
 
        var primitiveArgsMethod = type.GetMethod("PrimitiveArgs");
        var primitiveArgs = new object[] { 3, false };
        RavenDataAttribute.SaveData(primitiveArgsMethod, primitiveArgs);
 
        var complexArgsMethod = type.GetMethod("ComplexArgs");
        var complexArgsModel = new ComplexArgsModel
        {
            IsDivisibleByTwo = true,
            Number = 4
        };
        RavenDataAttribute.SaveData(complexArgsMethod, complexArgsModel);
    }
 
    public class ComplexArgsModel
    {
        public int Number { get; set; }
        public bool IsDivisibleByTwo { get; set; }
    }
}

Saturday, June 14, 2014

NUnit TestCase, the Data Driven Unit Test

A while back I wrote a blog post about data driven unit testing with xUnit. Back then a reader had to correct me because I did not think that NUnit had support for such things.

NUnit 2.5 added a slew of great features for authoring your own data driven unit tests. Perhaps best of all is the amazing support that ReSharper offers for the NUnit test cases.

You really should be using these amazing features when authoring your unit tests!

Data Driven NUnit Samples

// Here is a simple example that is the equivalent of an
// inline data attribute from xUnit.
 
[TestCase(1, 2, 3)]
[TestCase(2, 3, 5)]
public void SimpleSumCase(int a, int b, int expected)
{
    var actual = a + b;
    Assert.AreEqual(expected, actual);
}
 

Sunday, May 25, 2014

Three Things that all Applications MUST Have

This is the first in a three part series:

  1. Three Things that all Applications MUST Have
  2. Three Things that all Applications SHOULD Have
  3. Three Things that all Applications SHOULD WANT to Have

I feel very strongly that when you start a new project you should spend your first day or two just setting up a few basic utilities. For every hour you spend at the beginning of a project setting up these tools you will save yourself days down the line.

1. Logging

What is your application doing? How can you debug it? Will that work in all environments? The go to answer for these questions should always be logging!

I am constantly amazed at how many applications do not have a logger. To be fair, most of the time when I do not see a logger it is because the application is small or started out as a one off project. However to me that is all the more reason to just take the time and setup a logger right from a project's inception, then you know it will always be there. Thick client, thin client, or back end service, it should have a logger!

2. Dependency Injection

Dependency Injection is a pattern that drives a lot of best practices: it allows you to loosely couple your modules, forces you to consider the number dependencies any given module requires, and perhaps most importantly it makes your code very testable. The inversion of control that dependency injection provides also enables you to refactor and test in ways that are almost unachievable without it.

It can take a little while to fully understand dependency injection, especially the intricacies of lifetime management, but once you understand the fundamentals you can apply that knowledge to any language and any framework.

3. A Test Project

There is no reason not to have a test project as part of your solution. Regardless of how you feel about Test Driven Development (TDD) as a best practice we should all be able to agree that unit testing does provide value and is a good thing.

I encourage you to start simple: just create a test project with ONE unit test inside of it. Even if you do not have time to write tests right now, just having the project already setup will enable you to write them later. Additionally, just thinking about writing unit tests encourages you to author more testable code; so if absolutely nothing else then just use your test project as a best practices placebo!

Continue reading part 2: Three Things that all Applications SHOULD Have

Enjoy,
Tom

Tuesday, March 11, 2014

Migrating from Moq to NSubstitute

Mocking is a necessary evil for unit testing.

Fortunately frameworks like NSubstitute make it painless setup your mock services. NSubstitute offers a fluent API that requires few lambdas and no calls to an Object property. You just get back the interface that you are substituting and work with it directly. Frankly, NSubstitute is so easy to work with that it almost seems like magic!

Below is a visual representation of equivalent commands between Moq and NSubstitute:

NSubstitute

[Fact]
public void NSubstitute()
{
    var tester = Substitute.For<ITester>();
 
--------------------------------------------
            
    var voidArg = String.Empty;
 
    tester
        .When(t => t.Void(Arg.Any<string>()))
        .Do(i => voidArg = i.Arg<string>());
 
    tester.Void("A");
    Assert.Equal("A", voidArg);
 
--------------------------------------------
 
    tester
        .Bool()
        .Returns(true);
                
    var boolResult = tester.Bool();
    Assert.Equal(true, boolResult);
 
--------------------------------------------
 
    tester
        .Int
        .Returns(1);
 
    var intResult = tester.Int;
    Assert.Equal(1, intResult);
 
--------------------------------------------
 
    tester.Received(1).Void("A");
 
--------------------------------------------
 
    tester.DidNotReceive().Void("B");
}

Moq

[Fact]
public void Moq()
{
    var tester = new Mock<ITester>();
            
    // Setup a callback for a void method. -------
 
    var voidArg = String.Empty;
 
    tester
        .Setup(t => t.Void(It.IsAny<string>()))
        .Callback<string>(s => voidArg = s);
 
    tester.Object.Void("A");
    Assert.Equal("A", voidArg);
 
    // Setup the result of a method. -------------
 
    tester
        .Setup(t => t.Bool())
        .Returns(true);
 
    var boolResult = tester.Object.Bool();
    Assert.Equal(true, boolResult);
 
    // Setup the result of a property. -----------
 
    tester
        .SetupGet(t => t.Int)
        .Returns(1);
 
    var intResult = tester.Object.Int;
    Assert.Equal(1, intResult);
 
    // Ensure that a function was called. --------
 
    tester.Verify(m => m.Void("A"), Times.Once);
 
    // Ensure that a function was NOT called. ----
 
    tester.Verify(m => m.Void("B"), Times.Never);
}

Enjoy,
Tom

Monday, November 18, 2013

XUnit.PhantomQ v.1.2 Released

Want to run client side QUnit tests from Visual Studio or your build server? Now it is easier than ever; just grab newly updated XUnit.PhantomQ v1.2 from NuGet!

XUnit.PhantomQ will allow you to execute your QUnit tests as XUnit tests. It supports both library and web projects, and features the ability to easily specify test files and their dependencies by real relative path from the root of your project.

XUnit.PhantomQ on NuGet
XUnit.PhantomQ Source on GitHub

Change Log for v1.2

My thanks to James M Greene and the other authors of the PhantomJS Runner; their work served as the model for this version's improved test result information.

  • Significantly improved test result information and error details.
  • Added console.log support.
  • Added test timeout configuration support.
  • Added QUnit module support.
  • Added QUnit result details to QUnitTest.Context

Sunday, October 20, 2013

Unit Testing and Dependency Injection, with xUnit InlineData and Unity

Inversion of control is great because it makes your code more testable; but you usually still have to write tests for each implementation of your interfaces. So what if your unit testing framework could just work directly with your container to make testing even easier? Well, xUnit can!

Below we define a custom data source for our xUnit theories by extending the InlineDataAttribute. This allows our data driven unit tests to resolve types via a container, and then inject those resolved objects straight into our unit tests.

Bottom line: This allows us to test more with less code!

The rest of post is very code heavy, so I strongly recommend that you start out by taking a look at sections 1 and 2 to get an idea of what we are trying to accomplish. :)

  1. Example Interfaces and Classes
  2. Example Unit Tests
  3. IocInlineDataResolver
  4. UnityInlineDataAttribute

Saturday, August 24, 2013

XUnit.PhantomQ v1.1

I recently blogged about how to Use XUnit to Run QUnit Tests. The initial v1.0 release of XUnit.PhantomQ did not support error messages, but now in v1.1 it supports the must have feature of bringing error messages back with failed test results.

XUnit.PhantomQ on NuGet
XUnit.PhantomQ Source on GitHub

Enjoy,
Tom

Thursday, August 1, 2013

PhantomJS, the Headless Browser for your .NET WebDriver Tests

Did you know that Selenium already supports PhantomJS?

WebDriver is a specification for controlling the behavior of a web browser. PhantomJS is a headless WebKit scriptable with a JavaScript API. Ghost Driver is a WebDriver implementation that uses PhantomJS for its back-end. Selenium is a software testing framework for web applications. Selenium WebDriver is the successor to Selenium RC. The Selenium WebDriver NuGet Package is a .NET client for for Selenium WebDriver that includes support for PhantomJs via GhostDriver.

NuGet Packages

You need only install two NuGet packages in order to use PhantomJS with WebDriver. You will probably also want which ever Unit Testing framework you prefer. As always, I suggest xUnit.

  1. Selenium.WebDriver
  2. phantomjs.exe

PhantomJSDriver

After installing those, using the PhantomJSDriver is as easy as any other WebDriver!

const string PhantomDirectory =
    @"..\..\..\packages\phantomjs.exe.1.8.1\tools\phantomjs";
 
[Fact]
public void GoogleTitle()
{
    using (IWebDriver phantomDriver = new PhantomJSDriver(PhantomDirectory))
    {
        phantomDriver.Url = "http://www.google.com/";
        Assert.Contains("Google", phantomDriver.Title);
    }
}
Shout it

Enjoy,
Tom

Sunday, July 14, 2013

Use XUnit to Run QUnit Tests

I read a great article recently about Unit testing JavaScript in VisualStudio with ReSharper, written by Chris Seroka. As cool as this feature is, it left me with two questions:

  1. What about developers that do not have ReSharper?
  2. How do I run my JavaScript unit tests on a builder server?

It is no secret that I, absolutely, love, xUnit! Thus I decided to extend xUnit theories to be able to run QUnit tests by implementing a new DataAttribute.

Introducing XUnit.PhantomQ

XUnit.PhantomQ is a little NuGet package you can install to get access to the QUnitDataAttribute (see below for an example). This library will allow you to execute your QUnit tests as XUnit tests.

XUnit.PhantomQ supports both library and web projects, and features the ability to easily specify test files and their dependencies by real relative path to the root of your project.

XUnit.PhantomQ on NuGet
XUnit.PhantomQ Source on GitHub

QUnitData Attribute

Here is an example of writing some JavaScript, a file of QUnit tests, and then using an xUnit theory and a QUnitData Attribute to execute all of those tests right inside of Visual Studio.

// Contents of Demo.js
function getFive() {
    return 5;
}
 
// Contents of Tests.js
test('Test Five', function() {
    var actual = getFive();
    equal(actual, 5);
});
test('Test Not Four', function () {
    var actual = getFive();
    notEqual(actual, 4);
});
 
// Contents of QUnitTests.cs
public class QUnitTests
{
    [Theory, QUnitData("Tests.js", "Demo.js")]
    public void ReturnFiveTests(QUnitTest test)
    {
        test.AssertSuccess();
    }
}
 

Integrating XUnit, PhantomJS, and QUnit

So, how does this thing work under the hood? Below is the complete pipeline, step by step, of whenever the tests are executed:

  1. The XUnit test runner identifies your theory tests.
  2. The QUnitDataAttribute is invoked.
  3. A static helper locates PhantomJS.exe and the root folder of your project.
    • It will automatically walk up the folder structure and try to find PhantomJS.exe in your packages folder. However, you can override this and explicitly set the full path by adding an AppSetting to your config file:
      <add key="PhantomQ.PhantomJsExePath" value="C:/PhantomJS.exe" />
    • The same goes for the root of your project, you can override this location with another AppSetting to your config:
      <add key="PhantomQ.WorkingDirectory" value="C:/Code/DemoProject" />
  4. PhantomJS.exe is invoked as a separate process.
  5. The server loads up XUnit.PhantomQ.Server.js
  6. The server now opens XUnit.PhantomQ.html
  7. QUnit is set to autoRun false.
  8. Event handlers are added to QUnit for testDone and done.
  9. All of the dependencies are now added to the page as script tags.
  10. The test file itself is loaded.
  11. QUnit.start is invoked.
  12. The server waits for the test to complete.
  13. Upon completion the server reads the results out of the page.
  14. The tests and their results are serialized to a JSON dictionary.
  15. The result dictionary is written to the standard output.
  16. The resulting JSON string is read in from the process output.
  17. The results are deserialized using Newtonsoft.JSON
  18. The results are loaded into QUnitTest objects.
  19. The QUnitTest array is passed back from the DataAttribute
  20. Each test run finally calls the AssertSuccess and throws on failure.

...and that's (finally) all folks! If you have any questions, comments, or thoughts on how this could be improved, please let me know!

Shout it

Enjoy,
Tom

Monday, May 27, 2013

How to Test RavenDB Indexes

What if you could spin up an entire database in memory for every unit test? You can!

RavenDB offers an EmbeddableDocumentStore NuGet Package that allows you to create a complete in memory instance of RavenDB. This makes writing integration tests for your custom Indexes extremely easy.

The Hibernating Rhinos team makes full use of this feature by including a full suite of unit tests in their RavenDB solution. They even encourage people to submit pull requests to their GitHub repository so that they can pull those tests directly into their source. This is a BRILLIANT integration of all these technologies to both encourage testing and provide an extremely stable product.

So then, how do you test your RavenDB indexes? Great question; let's get into the code!

  1. Define your Document
public class Doc
{
    public int InternalId { get; set; }
    public string Text { get; set; }
}
  1. Define your Index
public class Index : AbstractIndexCreationTask<Doc>
{
    public Index()
    {
        Map = docs => from doc in docs
                      select new
                      {
                          doc.InternalId,
                          doc.Text
                      };
        Analyzers.Add(d => d.Text, "Raven.Extensions.AlphanumericAnalyzer");
    }
}
  1. Create your EmbeddableDocumentStore
  2. Insert your Index and Documents

In this example I am creating an abstract base class for my unit tests. The GetDocumentStore method provides an EmbeddableDocumentStore that comes pre-initialized with the default RavenDocumentsByEntityName index, your custom index, and a complete set of documents that have already been inserted. The Documents come from an abstract Documents property, which we will see implemented below in step 5.

protected abstract ICollection<TDoc> Documents { get; }
 
private EmbeddableDocumentStore NewDocumentStore()
{
    var documentStore = new EmbeddableDocumentStore
    {
        Configuration =
        {
            RunInUnreliableYetFastModeThatIsNotSuitableForProduction = true,
            RunInMemory = true
        }
    };
 
    documentStore.Initialize();
 
    // Create Default Index
    var defaultIndex = new RavenDocumentsByEntityName();
    defaultIndex.Execute(documentStore);
 
    // Create Custom Index
    var customIndex = new TIndex();
    customIndex.Execute(documentStore);
 
    // Insert Documents from Abstract Property
    using (var bulkInsert = documentStore.BulkInsert())
        foreach (var document in Documents)
            bulkInsert.Store(document);
 
    return documentStore;
}
  1. Write your Tests

These tests are testing a custom Alphanumeric analyzer. They will take in a series of lucene queries and assert that they match the correct internal Ids. These documents are being defined by our abstract Documents property from Step 4.

NOTE: Do not forget to include the WaitForNonStaleResults method on your queries, as your index may not be done building the first time you run your tests.

[Theory]
[InlineData(@"Text:Hello",              new[] {0})]
[InlineData(@"Text:file_name",          new[] {2})]
[InlineData(@"Text:name*",              new[] {2, 3})]
[InlineData(@"Text:my AND Text:txt",    new[] {2, 3})]
public void Query(string query, int[] expectedIds)
{
    int[] actualIds;
 
    using (var documentStore = NewDocumentStore())
    using (var session = documentStore.OpenSession())
    {
        actualIds = session.Advanced
            .LuceneQuery<Doc>("Index")
            .Where(query)
            .SelectFields<int>("InternalId")
            .WaitForNonStaleResults()
            .ToArray();
    }
 
    Assert.Equal(expectedIds, actualIds);
}
 
protected override ICollection<Doc> Documents
{
    get
    {
        return new[]
            {
                "Hello, world!",
                "Goodnight...moon?",
                "my_file_name_01.txt",
                "my_file_name01.txt"
            }
            .Select((t, i) => new Doc
            {
                InternalId = i,
                Text = t
            })
            .ToArray();
    }
}
Shout it

Enjoy,
Tom

Friday, October 26, 2012

xUnit Visual Studio Integration

Good news, everyone! It is actually very easy to get xUnit completely integrated with Visual Studio. You only need to install two plugins...

VS2010 - xUnit Test Runner Extension

This will support running tests with a Visual Studio test project.
This includes all of the VS features, such as code coverage!

https://github.com/quetzalcoatl/xvsr10/downloads

ReSharper - xUnit Contrib Plugin

This will allow ReSharper to detect and run xUnit tests.

http://xunitcontrib.codeplex.com/releases/view/92101
(If you are still running Resharper 6, then you will need the latest: v6.1.1)

Team Build (TFS) Integration

Integrating with xUnit your Team Foundation Server is a very tricky proposition, but it can be done. That, however, is a (rather long) blog post for another day!

Shout it

Enjoy,
Tom

Thursday, August 30, 2012

WebDrivers in Parallel

Here is a post that is long over due, and is finally getting published by request!

Concurrent WebDrivers

A WebDriver is not thread safe, but it is not required to be a singleton either. If you instantiate multiple drivers, they can all be run at the same time. If you cast a series of drivers into a collection of the IWebDriver interface, and then throw that into a Parallel ForEach, you have yourself one fun toy to play with!

So what are some uses of this?

Admittedly it is not a particularly common or practical use case to have multiple automated browser sessions running at the same time, but it can still come in handy. One fun application is to test website concurrency. You can do a minor load test of a webpage, or your can have two sessions trying to race each other for a limited resource.

...also, running WebDrivers in parallel can make for a killer demo!

Sample Code (xUnit Test)

public class ParallelDemo : IDisposable
{
    public IList<IWebDriver> Drivers { get; private set; }
 
    public ParallelDemo()
    {
        Drivers = new List<IWebDriver>
        {
            new InternetExplorerDriver(),
            new FirefoxDriver(),
            new ChromeDriver()
        };
    }
 
    public void Dispose()
    {
        foreach (var driver in Drivers)
        {
            driver.Close();
            driver.Dispose();
        }
    }
 
    [Fact]
    public void ParallelSearch()
    {
        Parallel.ForEach(Drivers, SearchForTom);
    }
 
    private static void SearchForTom(IWebDriver driver)
    {
        driver.Url = "https://www.google.com/#q=tom+dupont";
        var firstResult = driver.FindElement(By.CssSelector("h3 > a.l"));
        Assert.Contains("Tom DuPont .NET", firstResult.Text);
    }
}
Shout it

Enjoy,
Tom

Saturday, April 14, 2012

xUnit Theory, the Data Driven Unit Test

Update: I have also written a post about NUnit's Data Driven TestCaseAttribute.

Do you like copying and pasting code? Neither do I.

A good set of unit tests often end up reusing the same code with varied inputs. Rather than copy and paste that test code over and over, we can use the pattern of data driven unit tests to help streamline our test fixtures. This is the practice of having a single test definition be invoked and count as multiple tests at run time. This also enables us to do other dynamic things, such as configuring our unit tests from external sources. :)

I frequently use MSTest, but it's data driven tests inconveniently require you to define a DataSource. (Updated) Come to find out NUnit does offer data driven unit tests with their TestCaseSource attribute. Meanwhile xUnit offers several lightweight and simple options for defining data driven tests, which it refers to as theories.

Let's take a look at some of xUnit's Theory data sources:

InlineData Example

public class StringTests1
{
    [Theory,
    InlineData("goodnight moon", "moon", true),
    InlineData("hello world", "hi", false)]
    public void Contains(string input, string sub, bool expected)
    {
        var actual = input.Contains(sub);
        Assert.Equal(expected, actual);
    }
}

PropertyData Example

public class StringTests2
{
    [Theory, PropertyData("SplitCountData")]
    public void SplitCount(string input, int expectedCount)
    {
        var actualCount = input.Split(' ').Count();
        Assert.Equal(expectedCount, actualCount);
    }
 
    public static IEnumerable<object[]> SplitCountData
    {
        get
        {
            // Or this could read from a file. :)
            return new[]
            {
                new object[] { "xUnit", 1 },
                new object[] { "is fun", 2 },
                new object[] { "to test with", 3 }
            };
        }
    }
}

ClassData Example

public class StringTests3
{
    [Theory, ClassData(typeof(IndexOfData))]
    public void IndexOf(string input, char letter, int expected)
    {
        var actual = input.IndexOf(letter);
        Assert.Equal(expected, actual);
    }
}
 
public class IndexOfData : IEnumerable<object[]>
{
    private readonly List<object[]> _data = new List<object[]>
    {
        new object[] { "hello world", 'w', 6 },
        new object[] { "goodnight moon", 'w', -1 }
    };
 
    public IEnumerator<object[]> GetEnumerator()
    { return _data.GetEnumerator(); }
 
    IEnumerator IEnumerable.GetEnumerator()
    { return GetEnumerator(); }
}
kick it on DotNetKicks.com

Happy testing!
Tom

Real Time Web Analytics