testfx icon indicating copy to clipboard operation
testfx copied to clipboard

ClassCleanup not called in base class

Open pi3k14 opened this issue 8 months ago • 5 comments

Describe the bug

MSTest.TestFramework 3.0.4

ClassCleanup method in base class not called

[TestClass]
public class BaseClass
{
    [ClassCleanup]
    public static void ClassCleanupBase()
    {
        Console.WriteLine(nameof(BaseClass) + nameof(ClassCleanupBase));
    }
}

[TestClass]
public class UnitTest1 : BaseClass
{
    [TestMethod]
    public void TestMethod1()
    {
        Console.WriteLine(nameof(TestMethod1));
    }
/*
    [ClassCleanup]
    public static void ClassCleanup()
    {
        Console.WriteLine(nameof(UnitTest1) + nameof(ClassCleanup));
    }
*/
}

Additional context

Verified in debuger. Also mentioned in Class Initialize inheritance #143 The commented method works.

pi3k14 avatar Dec 07 '23 07:12 pi3k14

Hi @pi3k14,

I confirm that something is not working fine here. I have tried the various options and I confirm that the base is never called.

Evangelink avatar Dec 07 '23 08:12 Evangelink

I cannot find a single place where this works (I am writing to Trace.WriteLine, to make sure the output collector is simply not missing it). Looking at the fixes from PRs the fix that was supposed to implement and fix this is in 2.0.0 and 2.1.0 ( https://github.com/microsoft/testfx/pull/577 https://github.com/microsoft/testfx/pull/660 ) , still that does not work for me, so maybe I am just doing it wrong?

```cs
// file GlobalUsings.cs
global using Microsoft.VisualStudio.TestTools.UnitTesting;
<!-- file mstest1.csproj -->
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net7.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>

    <IsPackable>false</IsPackable>
    <IsTestProject>true</IsTestProject>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
    <PackageReference Include="MSTest.TestAdapter" Version="2.2.8" />
    <PackageReference Include="MSTest.TestFramework" Version="2.2.8" />
  </ItemGroup>

</Project>

// file UnitTest1.cs
using System.Diagnostics;

namespace mstest1;

[TestClass]
public class BaseClass
{
    [ClassCleanup(inheritanceBehavior: InheritanceBehavior.BeforeEachDerivedClass)]
    public static void ClassCleanupBase()
    {
        Trace.WriteLine("base cleanup");
    }
}

[TestClass]
public class UnitTest1 : BaseClass
{
    [TestMethod]
    public void TestMethod1()
    {
        Trace.WriteLine("Test method");
    }

    [ClassCleanup(inheritanceBehavior: InheritanceBehavior.BeforeEachDerivedClass)]
    public static void ClassCleanup()
    {
        Trace.WriteLine("class cleanup");
    }

}

No matter the combination of the class cleanup I simply don't see Trace.WriteLine("base cleanup"); in my output.

(in DebugView++: image )

nohwnd avatar Dec 14 '23 16:12 nohwnd

Interesting... I was looking at why our acceptance tests are working and noticed that we have also a [ClassInitialize] and it seems that having it causes the cleanup to be called while not having it results in the behavior observed in this issue.

Evangelink avatar Dec 15 '23 09:12 Evangelink

Ok so the problem is way bigger than expected... We need a huge refactoring of the class cleanup handling.

Evangelink avatar Dec 15 '23 15:12 Evangelink

As per @Evangelink comment above

Workaround

Declare your class cleanup method with BeforeEachDerivedClass inheritance behavior, and define a dummy class initialize method with same setting.

[ClassCleanup(InheritanceBehavior.BeforeEachDerivedClass)]
public static void ClassCleanup()
{
  ...
}

[ClassInitialize(InheritanceBehavior.BeforeEachDerivedClass)]  public static void ClassInitialize(TestContext _) { }

pi3k14 avatar Jan 05 '24 11:01 pi3k14