【问题标题】:One test watcher to report results of individual tests in JUnit Suite一个测试观察者报告 JUnit Suite 中单个测试的结果
【发布时间】:2016-01-25 19:16:58
【问题描述】:

所以我有一个套房,像这样:

@RunWith(Suite.class)
@Suite.SuiteClasses({TestClass1.class, TestClass2.class, TestClass3.class})
public class TestSuite {

    static List<ExtentTest> extentTestList = new ArrayList<>();

    @ClassRule
    public static ExtentWatcher extentWatcher = new ExtentWatcher() {
        @Override
        protected void starting(Description description) {
            extentTestList.addAll(extentWatcher.getTests());
        }
        @Override
        protected void finished(Description description) {
            extentWatcher.flushReports(extentTestList);
        }
    };
}

上面的代码有效,但问题是它导致我的 Watcher 报告套件的结果,而不是单个测试。此外,如果测试失败,套件仍会报告为通过。我的 Watcher 是这样的:

public class ExtentWatcher extends TestWatcher {

    // A little set up to give the report a date in the file name
    private DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
    private Date date = new Date();
    private String fileDate = dateFormat.format(date);
    private String reportName = "./Test_Report_" + fileDate + ".html";
    public ExtentReports extent;
    ArrayList<ExtentTest> testList = new ArrayList<>();

    public ExtentWatcher() {
        extent = createReport();
    }

        // If test passed, watcher will record this with Extent Reports
        @Override
        protected void succeeded(Description description) {
            ExtentTest test = extent.startTest(description.getDisplayName());
            test.log(LogStatus.PASS, "Test Run Successful");
            testList.add(test);
        }

        // Likewise in case of failure
        @Override
        protected void failed(Throwable e, Description description) {
            ExtentTest test = extent.startTest(description.getDisplayName());
            test.log(LogStatus.FAIL, "Test Failure: " + e.toString());
            testList.add(test);
        }

    /**
     * These methods do the legwork - this file is based off of an example I found @ www.kieftsoft.nl/?p=81
     * Eventually we can add some screenshot logic here, but just a clean test report and version info will do
     */

    private ExtentReports createReport() {
        // Create the report - Extent just needs a little config
        ExtentReports extent = new ExtentReports(reportName, false);
        extent.config().reportName("Test Report: " + fileDate);
        return extent;
    }

    public void flushReports(List<ExtentTest> testList) {
        // This ends the test and then sends (flushes) everything to the html document
        for(ExtentTest test : testList) extent.endTest(test);
        extent.flush();
    }

    public List<ExtentTest> getTests() {
        return testList;
    }
}

此代码可以很好地注释为单个测试的@Rule(每个测试单独的报告,不可取),但如上所述,这不适用于套件级别,我真的不确定如何让它工作。我在想我可以收集所有测试的列表,然后在套件中结束测试并刷新它们,这将允许 ExtentReport 给我所有测试的报告。但是,我无法具体获取单个测试结果 - 我将返回一项测试,其中 displayName() = 套件名称。

如何跟踪单个测试,然后在所有测试完成后刷新它们,并让 ExtentWatcher 逐个测试地处理通过/失败,而不是只为套件处理一次?

【问题讨论】:

  • 添加flushReports成功和失败后是否有效?
  • 与问题无关 - 为什么不更新到最新版本?
  • 不,如果我刷入成功或失败,我将获得每个测试的报告。我目前使用的是最新版本。
  • @SeeYaLater Automator:我遇到了同样的问题。有没有机会你能弄明白?
  • @user1466466 您是否尝试在ExtentReports 中也覆盖startingfinished

标签: java junit annotations webdriver automated-tests


【解决方案1】:

我使用 RunListener 实现,它将结果记录在一个文件中。首先,我有一个为每个测试套件调用的测试运行器类:

public Result run(String suite) {
    Class<?> suiteClass = null;
    try {
      suiteClass = Class.forName(suite);
    } catch (ClassNotFoundException ex) {
      return null;
    }
    JUnitCore core = new JUnitCore();
    this.testRun = new TestRun(testLogging, suite);
    core.addListener(new TestRunListener(testLogging, testRun));
    Result result = core.run(suiteClass);
    return(result);
}

TestRun 类是一个自定义类,它只计算已启动、通过、失败、忽略的测试数量。

TestRunListener 实现 org.junit.runner.notification.RunListener,并根据回调(例如 testFailure()、testFinished() 等)跟踪有关测试状态的信息。

@Override
public void testFailure(Failure failure) throws Exception {
  classLogger.log(Level.CONFIG, failure.getMessage());
  classLogger.log(Level.CONFIG, failure.getTestHeader());
  classLogger.log(Level.CONFIG, failure.getTrace());
  classLogger.log(Level.CONFIG, failure.getDescription().getDisplayName());
  if (failure.getException() != null) {
    classLogger.log(Level.CONFIG, failure.getException().getMessage());
  }
  super.testFailure(failure);

  Description description = failure.getDescription();
  Test test = processTestResult(TestStatus.FAIL, description);
  if (test == null) {
    classLogger.log(Level.SEVERE, "TEST IS NULL:" + description.getDisplayName());
    return;
  }

  classLogger.log(Level.CONFIG, failure.getMessage()+ " " + description.getDisplayName());

  test.setFailureMessage(description.getDisplayName());
  test.setFailureException(failure.getException());
  LogRecord record = new LogRecord(Level.CONFIG, failure.getMessage());
  record.setParameters(new Object[] { test, failure });
  testFailuresLogger.log(record);
}

【讨论】:

    【解决方案2】:

    上面的代码有效,但问题是它导致了我的 Watcher 报告套件的结果,而不是单个测试。

    TestSuite 类中指定的ClassRule 在类级别执行,不能针对每个单独的测试执行。因此,您的观察者不会报告个别测试。

    由于您有兴趣为每个单独的测试级别列出事件,因此您可以使用org.junit.runner.notification.RunListener(而不是 Watcher)。为了避免在每个测试类中指定监听器,您可以实现自己的 Suite 测试运行器,它会自动注册自定义的 RunListener。

    例如:

    public class SuiteRunner extends Suite {
        public SuiteRunner(Class<?> klass) throws InitializationError {
            super(klass, new JUnit4Builder());
        }
    
        @Override
        public void run(RunNotifier notifier) {
            notifier.addFirstListener(new RunListener() {
                @Override
                public void testRunStarted(Description description) throws Exception {
                    // add to watcher
                }
    
                @Override
                public void testFailure(Failure failure) throws Exception {
                    // add to watcher
                }
    
            });
            super.run(notifier);
        }
    }
    

    并在您的测试套件类中指定此运行器

    @RunWith(SuiteRunner.class)
    @Suite.SuiteClasses({ MyTest.class , MyTest2.class })
    public class TestSuite {
        @ClassRule
        public static ExtentWatcher watcher = new ExtentWatcher();
    }
    

    希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-29
      • 1970-01-01
      • 2012-11-11
      • 2023-03-05
      • 1970-01-01
      • 1970-01-01
      • 2011-06-10
      • 1970-01-01
      相关资源
      最近更新 更多