13

We are running nightly builds which at the end run all of our UnitTest using the MsTest framework.

We must have 100% pass rate, so if one fails there is no point running the others; hence we will like to stop the execution on the first failed test.

Is there anyway we can do achieve it?

jessehouwing
  • 106,458
  • 22
  • 256
  • 341
Alon1980
  • 1,225
  • 1
  • 16
  • 30

1 Answers1

0

Are you really sure you want to throw away test results?

Say somebody has a bad day and introduces multiple bugs A, B, and C into your code. You might only find out about A on Monday, so you fix that, and you don't know about issue B until Tuesday, and then you don't fix C until Wednesday. But since you were missing test coverage for half a week, bugs introduced Monday aren't discovered until days after they were introduced, and it's more expensive and takes longer to fix them.

If it doesn't cost you much to keep running the tests after a failure, isn't that information useful?


That said, hacking together a fix in your test libraries wouldn't be that hard. Have all possible codepaths of test failure set a static variable StopAssert.Failed = true; (probably by wrapping calls to Assert and catching AssertFailedExceptions. Then just add [TestInitialize()] methods to each test class to stop each test after a failure!

public class StopAssert
{
    public static bool Failed { get; private set; }

    public static void AreEqual<T>(T expected, T actual)
    {
        try
        {
            Assert.AreEqual(expected, actual);
        }
        catch
        {
            Failed = true;
            throw;
        }
    }

    // ...skipping lots of methods. I don't think inheritance can make this easy, but reflection might?

    public static void IsFalse(bool condition)
    {
        try
        {
            Assert.IsFalse(condition);
        }
        catch
        {
            Failed = true;
            throw;
        }
    }
}


[TestClass]
public class UnitTest1
{
    [TestInitialize()]
    public void Initialize()
    {
        StopAssert.IsFalse(StopAssert.Failed);
    }

    [TestMethod]
    public void TestMethodPasses()
    {
        StopAssert.AreEqual(2, 1 + 1);
    }

    [TestMethod]
    public void TestMethodFails()
    {
        StopAssert.AreEqual(0, 1 + 1);
    }

    [TestMethod]
    public void TestMethodPasses2()
    {
        StopAssert.AreEqual(2, 1 + 1);
    }
}

[TestClass]
public class UnitTest2
{
    [TestInitialize()]
    public void Initialize()
    {
        StopAssert.IsFalse(StopAssert.Failed);
    }

    [TestMethod]
    public void TestMethodPasses()
    {
        StopAssert.AreEqual(2, 1 + 1);
    }

    [TestMethod]
    public void TestMethodFails()
    {
        StopAssert.AreEqual(0, 1 + 1);
    }

    [TestMethod]
    public void TestMethodPasses2()
    {
        StopAssert.AreEqual(2, 1 + 1);
    }
}
Carl Walsh
  • 6,100
  • 2
  • 46
  • 50
  • Anyone have a way to do this with configuration settings? We have a lot of code that would need to be modified :( – Steve Feb 19 '16 at 18:06
  • "If it doesn't cost you much to keep running the tests after a failure, isn't that information useful?" - sometimes not. I have the same in a scenario where one error creates cascades down. I want to stop as soon as the first happens because i need to find the error that causes the cascade. – TomTom Jan 28 '20 at 15:13