Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SpecFlow - running parallel tests

I'm implementing tests using SpecFlow that have nothing to do with each other. Is there config option for SpecFlow that enables parallel test execution? I'm using VS10 and MSTest runner that supports running "up to 5 parallel unit tests" as they claim in documentation.

Thanks, max.yz

like image 751
max.yz Avatar asked May 22 '11 08:05

max.yz


1 Answers

I moved away from MSTest to MbUnit to achieve this. You can achieve parallelism at test fixture level with MbUnit using the ParallelizableAttribute. However as the test fixtures are generated from the .feature Gherkin files I had to grab the SpecFlow source code and modify the MbUnitTestGeneratorProvider class in the TechTalk.SpecFlow.Generator project to output the ParallelizableAttribute. So you end up with something like this:

public class MbUnitTestGeneratorProvider : IUnitTestGeneratorProvider
{
    private const string TESTFIXTURE_ATTR = "MbUnit.Framework.TestFixtureAttribute";
    private const string PARALLELIZABLE_ATTR = "MbUnit.Framework.ParallelizableAttribute";
    private const string TEST_ATTR = "MbUnit.Framework.TestAttribute";
    private const string ROWTEST_ATTR = "MbUnit.Framework.RowTestAttribute";
    private const string ROW_ATTR = "MbUnit.Framework.RowAttribute";
    private const string CATEGORY_ATTR = "MbUnit.Framework.CategoryAttribute";
    private const string TESTSETUP_ATTR = "MbUnit.Framework.SetUpAttribute";
    private const string TESTFIXTURESETUP_ATTR = "MbUnit.Framework.FixtureSetUpAttribute";
    private const string TESTFIXTURETEARDOWN_ATTR = "MbUnit.Framework.FixtureTearDownAttribute";
    private const string TESTTEARDOWN_ATTR = "MbUnit.Framework.TearDownAttribute";
    private const string IGNORE_ATTR = "MbUnit.Framework.IgnoreAttribute";
    private const string DESCRIPTION_ATTR = "MbUnit.Framework.DescriptionAttribute";

    public bool SupportsRowTests { get { return true; } }

    public void SetTestFixture(CodeTypeDeclaration typeDeclaration, string title, string description)
    {
        typeDeclaration.CustomAttributes.Add(
            new CodeAttributeDeclaration(
                new CodeTypeReference(TESTFIXTURE_ATTR)));

        typeDeclaration.CustomAttributes.Add(
            new CodeAttributeDeclaration(
                new CodeTypeReference(PARALLELIZABLE_ATTR)));

        SetDescription(typeDeclaration.CustomAttributes, title);
    }

If you compile this up and use it you'll end up with parallelizable test fixtures:

[System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "1.6.1.0")]
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[MbUnit.Framework.TestFixtureAttribute()]
[MbUnit.Framework.ParallelizableAttribute()]
[MbUnit.Framework.DescriptionAttribute("Test")]
public partial class TestFeature
{

The only problem with this as it stands is that you will need to make sure that test fixtures do not conflict with one another. That is to say, a test from one fixture adds or modifies a database row that breaks a test that is running at the same time as it. There are ways around this but that is probably out of scope of your original question.

Alex.

like image 159
Alex Webber Avatar answered Sep 22 '22 06:09

Alex Webber