Search code examples
c#seleniummstesttest-results

Get TestResult in MSTest TestCleanup in C#


I want to use TestResult in TestCleanup() to get some infos on the tests. But I don't know how to initialize TestResult object and get it. I want the same behavior that TestContext object.

Thanks

private static TestContext _testContext;
[ClassInitialize]
public static void SetupTests(TestContext testContext)
{
    _testContext = testContext;
}

If I can't access TestResult in TestCleanup, how can I write all the testresult to a csv file after all test finished?


Solution

  • You cannot access TestResult object in TestCleanup because it doesn't exist at this stage yet. Time spent in TestCleanup and TestInitialize are combine to TestResult.Duration property during test execution. You can easily test it by putting something like:

    [TestCleanup]
    public void TestCleanup()
    {
        Thread.Sleep(1000);
    }
    

    in your fast executing TestMethod. Or you can check Invoke method on TestMethodInfo: https://github.com/microsoft/testfx/blob/167533cadfd2839641fc238d39ad2e86b4262be1/src/Adapter/MSTest.CoreAdapter/Execution/TestMethodInfo.cs#L127

    This method will run your test. You can see where watch.Start() and watch.Stop() are placed, and where ExecuteInternal method is executed. This method will run RunTestInitializeMethod and RunTestCleanupMethod between Start and Stop.

    Your only solution is to combine all TestResults from your test class and then access them in your ClassCleanup method.

    You can do it by implementing your own TestMethodAttribute and overriding an Execute method. Then, you can save all results in a static property - Results in TestResultCollection class - and access it in TestCleanup method. Here is small example:

    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using System.Collections.Generic;
    
    namespace UnitTestProject
    {
        [TestClass]
        public class UnitTest
        {
            [ClassCleanup]
            public static void ClassCleanUp()
            {
                // Save TestResultCollection.Results in csv file
            }
    
            [MyTestMethod]
            public void TestMethod()
            {
                Assert.IsTrue(true);
            }
        }
    
        public static class TestResultCollection
        {
            public static Dictionary<ITestMethod, TestResult[]> Results { get; set; } = new Dictionary<ITestMethod, TestResult[]>();
        }
    
        public class MyTestMethodAttribute : TestMethodAttribute
        {
            public override TestResult[] Execute(ITestMethod testMethod)
            {
                TestResult[] results = base.Execute(testMethod);
    
                TestResultCollection.Results.Add(testMethod, results);
    
                return results;
            }
        }
    }
    

    Keep it mind that this is more like a hack, not a proper solution. Best option would be implementing your own csv logger and run it with vstest.console.exe with a csv switch.