在 TestNG 中将 SoftAssert 与并行执行结合使用会产生意想不到的结果

Using SoftAssert with Parallel Execution in TestNG produces unexpected results

我正在使用 rest-assured library to test our REST api that deals with data on sports. In short I have 2 different @Test methods to call per sport, one @Test method to make multiple GET requests to gather all athlete image urls and store in a static ArrayList, and the other method to instantiate a SoftAssert 对象,实际上在 for 循环中调用所有 url,并软断言 200 响应代码。然后我在第二个测试方法的末尾做一个 assertAll()。

例如-我有一个@Test getSoccerAthletes() 从响应中收集所有 urls,由于响应有限,该方法将重复直到所有运动员 urls 被收集一次 250 名运动员。在这个方法完成后,将执行 Soccer 的第二个 @Test 方法,它被命名为 testSoccerAthletes() 并且你可以看到它使用了 dependsOnMethods。下面是设置。

@Test(priority = 1)
    public static void getSoccerAthletes() {
        baseURI = "https://XXXXX";
        basePath = "XXXXX";

        Response res = given().queryParam("apikey", "XXXXXXXX")
                .queryParam("top", "250")
                .queryParam("skip", soccerSkip)
                .when().get();
        Assert.assertEquals(res.statusCode(), 200);

        JsonPath jPath = res.jsonPath();
        System.out.println("Soccer:  currentPageStart/totalCount " + jPath.getInt("currentPageStart")
                + "/" + jPath.getInt("totalCount"));

        if (soccerSkip == 0) {
            allSoccerAthletes = jPath.get("page.links.headshots.full");
        } else {
            ArrayList<String> athletes = jPath.get("page.links.headshots.full");
            allSoccerAthletes.addAll(athletes);
        }

        if (jPath.getInt("currentPageStart") + 250 < jPath.getInt("totalCount")) {
            soccerSkip += 250;
            getSoccerAthletes();
        }
    }

    @Test(priority = 2, dependsOnMethods = {"getSoccerAthletes"})
    public static void testSoccerAthletes() {
        SoftAssert softAssert = new SoftAssert();
        for (int i = 0; i < allSoccerAthletes.size(); i++) {
            String url = allSoccerAthletes.get(i);
            System.out.println("Soccer Athlete: " + i + "/" + allSoccerAthletes.size());

            Response res = when().head(url);
            softAssert.assertEquals(res.statusCode(), 200, "Failed url: " + url);

            if (i == allSoccerAthletes.size() - 1)
                allSoccerAthletes.clear();
        }
        softAssert.assertAll();
    }

我看到了不同的结果,其中一些因 @Test testXXXXAthletes 方法的失败而混淆。在线的第一个建议是在每个 @Test 方法(我目前为每个 testXXXXAthletes 方法)中实例化一个 SoftAssert 对象,所以不可能。

我开始倾向于线程安全问题,但我不确定如何推进解决方案。我认为存在线程安全问题的原因来自我研究过的一些文章,但并不完全理解。文章 --> https://learn2automate.wordpress.com/2017/07/13/parallel-testng-soft-assertions-the-right-way/, Retrieve test name on TestNG, https://github.com/rest-assured/rest-assured/issues/1420

如果能帮助解决我的问题,我们将不胜感激!顺便说一句,我还研究了使用 @DataProvider 注释,这让我想到了有关这些测试结构的其他问题。 getXXXAthletes 方法充当 testXXXAthletes 方法的数据提供者,但它们具有 dependsOnMethods 属性。我应该同时使用 DataProvider 和 dependsOnMethods,还是应该同时使用另一个?

进一步的研究证实了我关于 thread-safety 问题的理论。我能够得出结论,该问题与 SoftAssert 无关,而与 rest-assured 而非 thread-safe 有关。该信息可以在这里找到 --> https://github.com/rest-assured/rest-assured/pull/851

我找到了一个 thread-local 分支,其中有人好心地完成了 rest-assured thread-safe 的工作。我下载了 2 个文件 RestAssuredThreadLocal 和 RestAssuredThreadLocalImpl 可以在这里看到 --> https://github.com/rest-assured/rest-assured/commit/3307ba6c79c5547e88cea286d38e5c8a6d679229

下载这 2 个文件后,有一些错误需要解决,一些已弃用的方法需要更换。之后,我能够成功地 运行 我的 rest-assured 测试与 TestNG 并行并获得正确的结果。