testng-team / testng

TestNG testing framework
https://testng.org
Apache License 2.0
1.98k stars 1.02k forks source link

@Before and @After are not executed as expected when a combination of class and method level groupping is applied #2209

Closed zoomout closed 4 years ago

zoomout commented 4 years ago

TestNG Version

7.0.0 Reproduce using project in the archive: testng-groups.zip

Expected behavior

Note: this behavior is in version: 6.14.3

beforeClass
beforeMethod
groupK
afterMethod
afterClass

Actual behaviour

Note: this behavior is in version: 7.0.0

beforeClass
afterClass
afterMethod
beforeClass
beforeMethod
beforeMethod
groupK
afterMethod
afterMethod
beforeClass
beforeMethod
afterClass
afterClass

Is the issue reproducible on a runner?

Test case sample

Configure grouping and @BeforeClass, @BeforeMethod, @AfterClass, @AfterMethod as following in the MyTestClass. Run command: mvn clean test -Dgroups=groupM -DexcludedGroups=groupL

import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

@Test(groups = {"groupM"})
public class MyTestClass {

  @BeforeClass
  private void beforeClass(){
    System.out.println("beforeClass");
  }

  @BeforeMethod
  private void beforeMethod(){
    System.out.println("beforeMethod");
  }

  @Test(groups = {"groupK"})
  public void test1(){
    System.out.println("groupK");
  }

  @Test(groups = {"groupL"})
  public void test2(){
    System.out.println("groupL");
  }

  @AfterMethod
  private void afterMethod(){
    System.out.println("afterMethod");
  }

  @AfterClass
  private void afterClass(){
    System.out.println("afterClass");
  }

}
juherr commented 4 years ago

@krmahadevan The issue was introduced by https://github.com/cbeust/testng/pull/1995

The following test shows the issue:

public class Github2209Test extends SimpleBaseTest {

    @Test
    public void testGithub2209() {
        TestNG tng = create(Sample.class);
        tng.setGroups("groupM");
        tng.setExcludedGroups("groupL");

        InvokedMethodNameListener listener = new InvokedMethodNameListener(false);
        tng.addListener(listener);

        tng.run();

        assertThat(listener.getInvokedMethodNames()).containsExactly(
                "beforeClass",
                "beforeMethod",
                "test1",
                "afterMethod",
                "afterClass"
        );
    }
}

@Test(groups = {"groupM"})
public class Sample {

    @BeforeClass
    private void beforeClass() {
    }

    @BeforeMethod
    private void beforeMethod() {
    }

    @Test(groups = {"groupK"})
    public void test1() {
    }

    @Test(groups = {"groupL"})
    public void test2() {
    }

    @AfterMethod
    private void afterMethod() {
    }

    @AfterClass
    private void afterClass() {
    }
}

I'm a bit stuck with a solution. Do you have any idea?

krmahadevan commented 4 years ago

@juherr - Thanks for sharing that sample. Let me take a look at this.

juherr commented 4 years ago

@krmahadevan At the same time, something is weird here https://github.com/cbeust/testng/blob/910cf7b0af8a771559169372bc2cd75c12d1835f/src/main/java/org/testng/internal/TestNGMethodFinder.java#L173

I think it should be isAfterTestMethod but I don't have any test to confirm it :)