private boolean dependencyError( ITestResult testResult ) { String[] dependentMethods = testResult.getMethod().getMethodsDependedUpon(); List<ITestResult> failedTests = getFailedTests(); for (String dependentMethod : dependentMethods) { for (ITestResult failedTestResult : failedTests) { String failedMethodName = new StringBuilder().append(failedTestResult.getTestClass() .getName()) .append(".") .append(failedTestResult.getName()) .toString(); if (failedMethodName.equals(dependentMethod)) { logger.error("Dependent method '" + dependentMethod + "' failed!", failedTestResult.getThrowable()); return true; } } } return false; }
/** * [ITestListener] * Invoked each time a test is skipped. * * @param result {@code ITestResult} containing information about the run test * @see ITestResult#SKIP */ @Override public void onTestSkipped(ITestResult result) { // >>>>> ENTER workaround for TestNG bug // https://github.com/cbeust/testng/issues/1602 ITestContext context = result.getTestContext(); IInvokedMethod method = new InvokedMethod( result.getTestClass(), result.getMethod(), System.currentTimeMillis(), result); beforeInvocation(method, result, context); // <<<<< LEAVE workaround for TestNG bug synchronized (testListeners) { for (ITestListener testListener : testListeners) { testListener.onTestSkipped(result); } } }
@Test public void nullObjectsDataSuppliersShouldWork() { final InvokedMethodNameListener listener = run(NullObjectsDataSupplierTests.class); assertThat(listener.getSkippedBeforeInvocationMethodNames()) .hasSize(5) .containsExactly( "supplyExtractedNullObject()", "supplyNullArrayData()", "supplyNullCollectionData()", "supplyNullObjectData()", "supplyNullStreamData()" ); assertThat(EntryStream.of(listener.getResults()).values().toList()) .extracting(ITestResult::getThrowable) .extracting(Throwable::getMessage) .containsExactly( "java.lang.IllegalArgumentException: Nothing to return from data supplier. The following test will be skipped: NullObjectsDataSupplierTests.supplyNullCollectionData.", "java.lang.IllegalArgumentException: Nothing to return from data supplier. The following test will be skipped: NullObjectsDataSupplierTests.supplyNullStreamData.", "java.lang.IllegalArgumentException: Nothing to return from data supplier. The following test will be skipped: NullObjectsDataSupplierTests.supplyExtractedNullObject.", "java.lang.IllegalArgumentException: Nothing to return from data supplier. The following test will be skipped: NullObjectsDataSupplierTests.supplyNullArrayData.", "java.lang.IllegalArgumentException: Nothing to return from data supplier. The following test will be skipped: NullObjectsDataSupplierTests.supplyNullObjectData." ); }
public String getFailedTestScreenshotPath(final String testName, final String methodName) { Iterator<ITestResult> it2 = getMethodResults(testName, methodName).iterator(); List<String> reporterOutput = new ArrayList<String>(); String screenshotFileLink = ""; while (it2.hasNext()) { ITestResult result = it2.next(); reporterOutput = Reporter.getOutput(result); break; } for (String line : reporterOutput) { if (line.contains("[Console Log] Screenshot saved in")) { screenshotFileLink = line.substring(line.indexOf("in") + 3, line.length()); break; } } return screenshotFileLink; }
@Override public boolean retry(final ITestResult result) { try { config = ProjectConfigurator.initializeProjectConfigurationsFromFile("project.properties"); } catch (IOException e) { e.printStackTrace(); } int maxRetryCount = Integer.parseInt(config.getProperty("max.retry.count")); if (retryCount <= maxRetryCount) { LOGGER.info("Retry: " + retryCount + ", Rerunning Failed Test: " + result.getTestClass().getName()); retryCount++; return true; } return false; }
@Test public void verifyCanNotCapture() { ListenerChain lc = new ListenerChain(); TestListenerAdapter tla = new TestListenerAdapter(); TestNG testNG = new TestNG(); testNG.setTestClasses(new Class[]{ArtifactCollectorTestCases.class}); testNG.addListener((ITestNGListener) lc); testNG.addListener((ITestNGListener) tla); testNG.setGroups("canNotCapture"); testNG.run(); assertEquals(tla.getPassedTests().size(), 0, "Incorrect passed test count"); assertEquals(tla.getFailedTests().size(), 1, "Incorrect failed test count"); assertEquals(tla.getSkippedTests().size(), 0, "Incorrect skipped test count"); assertEquals(tla.getFailedButWithinSuccessPercentageTests().size(), 0, "Incorrect curve-graded success count"); assertEquals(tla.getConfigurationFailures().size(), 0, "Incorrect configuration method failure count"); assertEquals(tla.getConfigurationSkips().size(), 0, "Incorrect configuration method skip count"); ITestResult result = tla.getFailedTests().get(0); assertEquals(UnitTestArtifact.getCaptureState(result), CaptureState.CAN_NOT_CAPTURE, "Incorrect artifact provider capture state"); assertFalse(UnitTestCapture.getArtifactPath(result).isPresent(), "Artifact capture output path should not be present"); }
private List<Parameter> getParameters(final ITestResult testResult) { final Stream<Parameter> tagsParameters = testResult.getTestContext() .getCurrentXmlTest().getAllParameters().entrySet() .stream() .map(entry -> new Parameter().withName(entry.getKey()).withValue(entry.getValue())); final String[] parameterNames = Optional.of(testResult) .map(ITestResult::getMethod) .map(ITestNGMethod::getConstructorOrMethod) .map(ConstructorOrMethod::getMethod) .map(Executable::getParameters) .map(Stream::of) .orElseGet(Stream::empty) .map(java.lang.reflect.Parameter::getName) .toArray(String[]::new); final String[] parameterValues = Stream.of(testResult.getParameters()) .map(this::convertParameterValueToString) .toArray(String[]::new); final Stream<Parameter> methodParameters = range(0, min(parameterNames.length, parameterValues.length)) .mapToObj(i -> new Parameter().withName(parameterNames[i]).withValue(parameterValues[i])); return Stream.concat(tagsParameters, methodParameters) .collect(Collectors.toList()); }
@Test public void verifyHappyPath() { ListenerChain lc = new ListenerChain(); TestListenerAdapter tla = new TestListenerAdapter(); TestNG testNG = new TestNG(); testNG.setTestClasses(new Class[]{ArtifactCollectorTestCases.class}); testNG.addListener((ITestNGListener) lc); testNG.addListener((ITestNGListener) tla); testNG.setGroups("testPassed"); testNG.run(); assertEquals(tla.getPassedTests().size(), 1, "Incorrect passed test count"); assertEquals(tla.getFailedTests().size(), 0, "Incorrect failed test count"); assertEquals(tla.getSkippedTests().size(), 0, "Incorrect skipped test count"); assertEquals(tla.getFailedButWithinSuccessPercentageTests().size(), 0, "Incorrect curve-graded success count"); assertEquals(tla.getConfigurationFailures().size(), 0, "Incorrect configuration method failure count"); assertEquals(tla.getConfigurationSkips().size(), 0, "Incorrect configuration method skip count"); ITestResult result = tla.getPassedTests().get(0); assertNull(UnitTestArtifact.getCaptureState(result), "Artifact provider capture state should be 'null'"); assertNull(UnitTestCapture.getArtifactPath(result), "Artifact capture should not have been requested"); }
public Long getMethodExecutionTime(String testName, String methodName) { long startTime = Long.MAX_VALUE; long endTime = Long.MIN_VALUE; Iterator<ITestResult> it2 = getMethodResults(testName, methodName).iterator(); while (it2.hasNext()) { ITestResult result = it2.next(); startTime = result.getStartMillis(); endTime = result.getEndMillis(); break; } return (endTime - startTime); }
/** * [IConfigurationListener2] * Invoked before a configuration method is invoked. * * @param tr test result object for the associated configuration method */ @Override public void beforeConfiguration(ITestResult tr) { synchronized(configListeners2) { for (IConfigurationListener2 configListener : Lists.reverse(configListeners2)) { configListener.beforeConfiguration(tr); } } }
private String getTestName( ITestResult result ) { String testName = result.getName(); // check if there is a description annotation and get the test name Method testCaseMethod = result.getMethod().getConstructorOrMethod().getMethod(); Description testCaseDescription = testCaseMethod.getAnnotation(Description.class); if (testCaseDescription != null && testCaseDescription.name().length() > 0) { testName = testCaseDescription.name(); } return testName; }
/** * Record the path at which the specified artifact was store in the indicated test result. * @param artifactPath path at which the captured artifact was stored * @param result TestNG test result object */ private static void recordArtifactPath(Path artifactPath, ITestResult result) { @SuppressWarnings("unchecked") List<Path> artifactPaths = (List<Path>) result.getAttribute(ARTIFACT_PATHS); if (artifactPaths == null) { artifactPaths = new ArrayList<>(); result.setAttribute(ARTIFACT_PATHS, artifactPaths); } artifactPaths.add(artifactPath); }
private void endTestcaseWithSkipStatus( ITestResult testResult, ITestContext context ) { //Check if the test was successfully started, if not - make it started and then end it with failure String testName = testResult.getMethod().toString(); if (!testName.equals(currentTestcaseName)) { startTestcase(testResult); } sendTestEndEventToAgents(); if (configurationError(context)) { // test is skipped due to configuration error logger.info(MSG__TEST_SKIPPED_CONFIGURATION, testResult.getThrowable()); } else if (dependencyError(testResult, context)) { // test is skipped due to dependency error logger.info(MSG__TEST_SKIPPED_DEPENDENCY, testResult.getThrowable()); } else { // we do not know the exact problem logger.fatal(MSG__TEST_SKIPPED_UNRECOGNIZED_REASON, testResult.getThrowable()); } currentTestcaseName = null; lastTestcaseResult = TestCaseResult.SKIPPED.toInt(); // end test case logger.endTestcase(TestCaseResult.SKIPPED); }
/** * 测试方法拦截器、所有测试方法在执行开始、执行中、执行完成都会在此方法中完成 * @param callBack * @param testResult */ @Override public void run(IHookCallBack callBack, ITestResult testResult) { // 如果测试方法上有@Ignore注解,则跳过测试框架直接执行测试方法 if (isIgnoreAnnotation(getTestMethod(testResult))) { callBack.runTestMethod(testResult); } }
@Override public void afterInvocation(final IInvokedMethod method, final ITestResult testResult) { if (method.isTestMethod()) { addByteAttachmentAsync("Test log", "text/plain", "afterInvocationContent"::getBytes); if (!testResult.isSuccess()) { addStreamAttachmentAsync("Failure screenshot", "image/png", () -> getSystemResourceAsStream("attachments/screenshot.png")); } } }
@Override @CheckReturnValue public void afterInvocation(final IInvokedMethod method, final ITestResult testResult) { if (method.isTestMethod()) { final String fileName = String.format("http://localhost:4444/video/%s.mp4", testResult.getAttribute("sessionId")); attachUri("Video", fileName); } }
@Override public void afterInvocation(final IInvokedMethod method, final ITestResult testResult) { if (method.isTestMethod() && testResult.getStatus() == SUCCESS) { try { getSoftAssert().assertAll(); } catch (AssertionError e) { testResult.getTestContext().getPassedTests().removeResult(testResult.getMethod()); testResult.setStatus(TestResult.FAILURE); testResult.setThrowable(e); } THREAD_LOCAL_CONTAINER_FOR_SOFT_ASSERTIONS.remove(); } }
/** * Store the specified object in the attributes collection. * * @param obj object to be stored; 'null' to discard value * @return (optional) specified object */ private <T> Optional<T> set(T obj) { ITestResult result = Reporter.getCurrentTestResult(); Optional<T> val = TestBase.optionalOf(obj); result.setAttribute(key, val); return val; }
@Override public void adjustTimeout(long adjust) { ITestResult testResult = Reporter.getCurrentTestResult(); if (testResult != null) { long timeout = testResult.getMethod().getTimeOut(); if (timeout > 0) { testResult.getMethod().setTimeOut(timeout + adjust); } } }
public void onTestSkipped(ITestResult result) { System.err.println("TestMethod Skipped : " + getTestMethodNameFromResult(result)); allSkippedTestMethods.add(getTestMethodNameFromResult(result)); progressingTestMethods.remove(getTestMethodNameFromResult(result)); testsPending.remove(getTestMethodNameFromResult(result)); update(); }
public void setupDriver(final XmlConfig context, final ITestResult testResult) { final List<WebDriverProvider> webDriverProviders = getWebDriverProviders(); DRIVER_CONTAINER.set( StreamEx.of(webDriverProviders) .findFirst(this::isWebDriverProviderMatching) .map(wdp -> wdp.createDriver(getCurrentBrowser(context), context)) .map(d -> Tuple.of(d, new WebDriverWait(d, WD_CONFIG.wdWaitTimeout()))) .orElse(null)); injectSessionId(testResult); }
private String getTestDescription( Class<?> testClass, String suiteName, String testName, ITestResult result ) { // Look for a test description Method testCaseMethod = result.getMethod().getConstructorOrMethod().getMethod(); // 1. in ATS @Description annotation Description atsDescription = testCaseMethod.getAnnotation(Description.class); if (atsDescription != null && atsDescription.description().length() > 0) { return atsDescription.description(); } // 2. TestNG @Test annotation Test testngDescription = testCaseMethod.getAnnotation(Test.class); if (testngDescription != null && testngDescription.description().length() > 0) { return testngDescription.description(); } // 3. Javadoc for this test method if (javaFileContent == null) { saveJavaFileContent(testClass); } if (javaFileContent != null) { return parseFileForJavadoc(javaFileContent, testName); } return null; }
private List<ITestResult> getList(String listName, ITestContext context) { List<ITestResult> outputList = new ArrayList<>(); if (context.getAttributeNames().contains(listName)) { outputList = (List<ITestResult>) context.getAttribute(listName); } return outputList; }
@Test(groups = {"happyPath"}) public void testAttachedListeners() { System.out.println("testAttachedListeners"); ITestResult result = Reporter.getCurrentTestResult(); Optional<ChainedListener> optChained = ListenerChain.getAttachedListener(result, ChainedListener.class); assertTrue(optChained.isPresent()); Optional<ServiceLoadedListener> optService = ListenerChain.getAttachedListener(result, ServiceLoadedListener.class); assertTrue(optService.isPresent()); }
@Override public void afterInvocation(IInvokedMethod iInvokedMethod, ITestResult iTestResult) { if(iInvokedMethod.isTestMethod() && ReflectionUtils.shouldBeInvoked(iInvokedMethod.getTestMethod().getRealClass(), MethodInGroupsListener.class)){ Stream.of(getAllMethods(iInvokedMethod.getTestMethod().getRealClass(), new Method[]{})) .filter(method -> method.isAnnotationPresent(AfterMethodInGroups.class)) .filter(method -> intersects(iInvokedMethod.getTestMethod().getGroups(), method.getAnnotation(AfterMethodInGroups.class).groups())) .sorted(Comparator.comparingInt(method -> method.getAnnotation(AfterMethodInGroups.class).priority())) .forEach(method -> { method.setAccessible(true); ReflectionUtils.invokeMethod(method, iTestResult.getInstance()); }); } }
/** * Return a unique number based on the test method parameters. */ private int getKey(ITestResult result) { Object[] params = result.getParameters(); if (params == null || params.length == 0) { return 0; } else { int key = result.getMethod().hashCode(); for (Object param : params) { key += FileUtils.toJson(param).hashCode(); } return key; } }
@Override public void beforeInvocation(final IInvokedMethod method, final ITestResult testResult) { if (method.isTestMethod()) { final String rawMethodName = method.getTestMethod().getMethodName(); final long currentThreadId = Thread.currentThread().getId(); threads.putIfAbsent(rawMethodName, new CopyOnWriteArrayList<>()); threads.computeIfPresent(rawMethodName, (s, l) -> StreamEx.of(l).append(currentThreadId).distinct().toList()); invokedMethodNames.add(getName(testResult)); } }
/** * Get the path at which to store artifacts. * * @param result TestNG test result object * @return artifact storage path */ default Path getArtifactPath(ITestResult result) { if (result != null) { return PathUtils.ReportsDirectory.getPathForObject(result.getInstance()); } else { return PathUtils.ReportsDirectory.ARTIFACT.getPath(); } }
@Override public void onTestSkipped(final ITestResult result) { final String name = getName(result); results.put(name, result); if (!skippedMethodNames.contains(name)) { skippedBeforeInvocationMethodNames.add(name); } }
@Override public void onTestSuccess(final ITestResult testResult) { final Current current = currentTestResult.get(); current.after(); getLifecycle().updateTestCase(current.getUuid(), setStatus(Status.PASSED)); getLifecycle().stopTestCase(current.getUuid()); getLifecycle().writeTestCase(current.getUuid()); }
@Override public void onTestSuccess(final ITestResult result) { final String name = getName(result); results.put(name, result); if (!succeedMethodNames.contains(name)) { throw new IllegalStateException("A succeed test is supposed to be invoked"); } }
private void startTestcase( ITestResult testResult ) { Class<?> testClass = testResult.getTestClass().getRealClass(); String suiteFullName = testClass.getName(); String suiteSimpleName = testClass.getSimpleName(); String testName = getTestName(testResult); String testInputArguments = getTestInputArguments(testResult); String testDescription = getTestDescription(testClass, suiteFullName, testName, testResult); // save the current testcase name currentTestcaseName = testResult.getMethod().toString(); //clear the last saved testcase result, since a new testcase is about to start lastTestcaseResult = -1; // start test case logger.startTestcase(suiteFullName, suiteSimpleName, testName, testInputArguments, testDescription); addScenarioMetainfo(testResult); // send TestStart event to all ATS agents TestcaseStateEventsDispacher.getInstance().onTestStart(); String testStartMessage = "[TestNG]: Starting " + suiteFullName + "@" + testName + testInputArguments; int passedRuns = RetryAnalyzer.getNumberPassedRuns(); if (passedRuns < 1) { logger.info(testStartMessage); } else { logger.warn(testStartMessage + " for " + (passedRuns + 1) + " time"); } }
@Override public void beforeInvocation(final IInvokedMethod method, final ITestResult testResult, final ITestContext context) { final ITestNGMethod testMethod = method.getTestMethod(); if (isSupportedConfigurationFixture(testMethod)) { ifSuiteFixtureStarted(context.getSuite(), testMethod); ifTestFixtureStarted(context, testMethod); ifClassFixtureStarted(testMethod); ifMethodFixtureStarted(testMethod); } }
@Override public byte[] getArtifact(ITestResult result) { if (willGet(result)) { setCaptureState(result, CaptureState.CAPTURE_SUCCESS); return String.format(ARTIFACT, result.getName()).getBytes().clone(); } else { setCaptureState(result, CaptureState.CAPTURE_FAILED); return new byte[0]; } }
@Test public void testSkipFromBefore() { ExecutionFlowController efc = new ExecutionFlowController(); TestListenerAdapter tla = new TestListenerAdapter(); TestNG testNG = new TestNG(); testNG.setTestClasses(new Class[]{SkipFromBefore.class}); testNG.addListener((ITestNGListener) efc); testNG.addListener((ITestNGListener) tla); testNG.setConfigFailurePolicy(FailurePolicy.CONTINUE); testNG.run(); assertEquals(tla.getFailedTests().size(), 0, "Unexpected test method failure"); assertEquals(tla.getConfigurationFailures().size(), 0, "Unexpected configuration method failure"); assertEquals(tla.getPassedTests().size(), 1, "Incorrect passed test count"); assertEquals(tla.getFailedTests().size(), 0, "Incorrect failed test count"); assertEquals(tla.getConfigurationSkips().size(), 1, "Incorrect configuration skip count"); assertEquals(tla.getSkippedTests().size(), 1, "Incorrect skipped test count"); ITestResult methodResult = tla.getSkippedTests().get(0); assertEquals(methodResult.getName(), "testMethod", "Incorrect skipped test name"); assertEquals(SkipFromBefore.fromBefore, SkipFromBefore.VALUE, "Incorrect [before] value"); assertEquals(methodResult.getAttribute(SkipFromBefore.ATTRIBUTE), SkipFromBefore.VALUE, "Incorrect [method] value"); assertEquals(SkipFromBefore.fromAfter, SkipFromBefore.VALUE, "Incorrect [after] value"); }
private <T extends Annotation> Stream<Label> getLabels(final ITestResult result, final Class<T> clazz, final Function<T, Label> extractor) { final List<Label> onMethod = getAnnotationsOnMethod(result, clazz).stream() .map(extractor) .collect(Collectors.toList()); if (!onMethod.isEmpty()) { return onMethod.stream(); } return getAnnotationsOnClass(result, clazz).stream() .map(extractor); }