testng icon indicating copy to clipboard operation
testng copied to clipboard

Method predecessors lookup and/or method sorting is broken in certain inheritance and naming setups

Open ptomaszek opened this issue 2 years ago • 0 comments

⁸### TestNG Version 7.8.0 on JDK 11 Temurin (Liniux and Windows) maven-surefire-plugin:3.1.2 aspectjweaver:1.9.20.1

Or check out the source code: https://github.com/ptomaszek/testng-pt-playground/tree/feature/testng-7.8.0-unexpected-failure

Expected behavior

Test passes

Actual behavior

Test fails

Is the issue reproducible on runner?

  • [X] Shell
  • [X] Maven
  • [ ] Gradle
  • [ ] Ant
  • [ ] Eclipse
  • [X] IntelliJ
  • [ ] NetBeans

Test case sample

Run the test (IntelliJ or mvn test) and note it fails. Then apply any solution from the comments and observe the test passes:

package com.example; // 1. to make the test PASS change to `org.example`

import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

import static org.testng.Assert.assertNotNull;

public class MyTest extends MyBaseTest {

    @BeforeClass
    public void beforeClass() {
        assertNotNull(dependency); // fails here
    }

    @Test
    public void test() {
    }
}

abstract class MyBaseTest implements MyInterface { // 2. alternatively, to make the test PASS remove `implements MyInterface`
    protected Object dependency;

    public void setDependency(Object dependency) {
    }

    @BeforeClass
    public void setupDependency() {
        dependency = new Object();
    }

    @BeforeClass(dependsOnMethods = "setupDependency")
    public void setupAdditionalDependency_() {  // 3. alternatively, to make the test PASS remove `_` from the method name
    }
}

interface MyInterface {

    void setDependency(Object dependency);

    default Object getDependency() { // 4. alternatively, to make the test PASS remove this method
        return null;
    }
}

Something that may direct you to the solution: Debug code at Graph:130 (at the end of topologicalSort()) and observe the object's state:

when PASS, you'll see:

m_strictlySortedNodes = {ArrayList@2282}  size = 2
0 = {ConfigurationMethod@2292} "MyTest.setupDependency()[pri:0, instance:null]"
1 = {ConfigurationMethod@2293} "MyTest.setupAdditionalDependency()[pri:0, instance:null]"

when FAIL, you'll see

m_strictlySortedNodes = {ArrayList@2283}  size = 3
0 = {ConfigurationMethod@2293} "MyTest.beforeClass()[pri:0, instance:null]" // I believe it should not be here, as the list should contain only independent (top level?) methods
1 = {ConfigurationMethod@2294} "MyTest.setupDependency()[pri:0, instance:null]"
2 = {ConfigurationMethod@2295} "MyTest.setupAdditionalDependency_()[pri:0, instance:null]"

ptomaszek avatar Oct 27 '23 15:10 ptomaszek