diff --git a/testng-core-api/src/main/java/org/testng/ITestResult.java b/testng-core-api/src/main/java/org/testng/ITestResult.java index 00649a4615..86a8c2d348 100644 --- a/testng-core-api/src/main/java/org/testng/ITestResult.java +++ b/testng-core-api/src/main/java/org/testng/ITestResult.java @@ -115,6 +115,13 @@ default List getSkipCausedBy() { */ String id(); + /** + * @return true if the current method (test|configuration) was executed by TestNG. + */ + default boolean wasExecuted() { + return !isNotRunning(); + } + /** * @return - true if the current test result is either {@link ITestResult#STARTED} or * {@link ITestResult#CREATED} diff --git a/testng-core/src/main/java/org/testng/internal/invokers/ConfigInvoker.java b/testng-core/src/main/java/org/testng/internal/invokers/ConfigInvoker.java index 9ecb0a4a45..efc9a9bdb3 100644 --- a/testng-core/src/main/java/org/testng/internal/invokers/ConfigInvoker.java +++ b/testng-core/src/main/java/org/testng/internal/invokers/ConfigInvoker.java @@ -285,18 +285,23 @@ public void invokeConfigurations(ConfigMethodArguments arguments) { arguments.getTestMethodResult()); testResult.setParameters(parameters); - runConfigurationListeners(testResult, arguments.getTestMethod(), true /* before */); - Object newInstance = computeInstance(arguments.getInstance(), inst, tm); if (isConfigMethodEligibleForScrutiny(tm)) { if (m_executedConfigMethods.add(arguments.getTestMethod())) { + runConfigurationListeners(testResult, arguments.getTestMethod(), true /* before */); invokeConfigurationMethod(newInstance, tm, parameters, testResult); } } else { + runConfigurationListeners(testResult, arguments.getTestMethod(), true /* before */); invokeConfigurationMethod(newInstance, tm, parameters, testResult); } copyAttributesFromNativelyInjectedTestResult(parameters, arguments.getTestMethodResult()); - runConfigurationListeners(testResult, arguments.getTestMethod(), false /* after */); + + if (testResult.wasExecuted()) { + // When it comes to "firstTimeOnly" configurations, some of them would NOT be run + // by TestNG. For those occurrences, DONOT run the listener. + runConfigurationListeners(testResult, arguments.getTestMethod(), false /* after */); + } if (testResult.getStatus() == ITestResult.SKIP) { Throwable t = testResult.getThrowable(); if (t != null) {