5

我有一个黄瓜场景,步骤使用assertEquals. 我的结果报告显示了对最终用户不友好的堆栈跟踪。我怎样才能压制它

  Scenario: Add two numbers
    Given I have two inputs "3" and "2"
    When I add them
    Then the output should be "15"

朱尼特

4

2 回答 2

1

您正确地观察到来自 Junit 测试的默认 XML 输出(假设您没有输出到 JSON 或文本,但您没有说)显示失败步骤的堆栈跟踪。这实际上不是黄瓜的事情。CucumberOptions在这里帮不了你。

你可以:

  1. 为您的测试使用不同的或自定义的 Runner,然后设置一个标签来控制输出中包含的内容,或者您​​选择的CI 软件将读取的内容。例如,用于执行此操作的 Confulence API API 告诉“调试器”如何
  2. Ant 脚本调整输出的相同类型的交易,因此不显示输出。学习如何使用任何脚本来启动 Cucumber JUnit 测试的一个很好的教程在这里
  3. 其他人通过实现 XMLJUnitResultFormatter API为 JUnit 构建了自定义格式化程序,在这里进行了更多解释-如何将 JUnit Ant 任务配置为仅在失败时生成输出?

希望能给你你所需要的。

于 2014-04-02T14:16:55.173 回答
1

我的 Cucumber-Selenium-Java 项目也面临同样的问题。在黄瓜报告中,它生成了大约 40 行堆栈跟踪。因此,它影响了报告的外观和感觉。最终用户/客户对此并不关心。因为他/她并不能真正弄清楚这个堆栈跟踪的实际用途。所以,我想出了下面的想法/方法。这有点棘手,但值得。

开始前的几点说明:

  1. 我们不能在所有情况下都完全禁用堆栈跟踪。但是我们可以修改堆栈跟踪,然后使用有用且缩短的堆栈跟踪重新抛出新异常。
  2. 您需要了解经常遇到的异常、错误。因此,我们可以根据异常创建自定义异常。
  3. 在堆栈跟踪中,它将从包装器 API 生成几行代码,从 Junit/TestNg 生成几行代码,为 java 和 selenium 生成几行代码,堆栈跟踪中只有一两行,实际上是我们的问题发生的地方。
  4. 我们的测试类必须在唯一的包中。这样,我们可以使用包名过滤堆栈跟踪跟踪,并获取实际问题的类名、行号和方法名,我们可以使用这些信息来引发自定义异常。因此,很容易找出实际发生的问题。在我的例子中,所有的类都在名为“page”的包中。如果您的类有多个包,那么您可以相应地在下面的代码中添加字符串条件。
  5. 我们需要将测试代码包装在 try-catch 块中。在捕获时,我们需要使用 Throwable 类而不是异常类。因为,如果有任何断言失败,那么 Exception 类将无法处理该问题,因为您知道所有断言都属于 Error 类,而 Throwable 是 Error 和 Exception 的父级。
  6. 如果我们在 catch 块中抛出新的异常,那么它将更改堆栈跟踪中的行号,而实际问题发生的地方。因此,很难弄清楚实际的问题线。为了避免它,我们需要获取实际问题的类名、行号、方法名并将其存储在 StackTraceElement 类中,并在抛出新异常时使用它。
  7. 像“NoSuchElementException”这样的异常在其原因中提供了很多信息,其中大部分并不是真正需要的,所以我们需要使用 String 类的 substring()、indexOf() 和 replaceAll() 方法来修改它的消息内容爪哇。然后,在新异常中提供修改后的信息。
  8. Throwable java 类中几个重要的 Java 方法及其描述: (i) getStackTrace():该方法将返回 StackTraceElement 类的数组。StackTraceElement 类将为我们提供发生问题的类名、方法名、行号。(ii) setStackTrace():此方法用于为新异常提供自定义堆栈跟踪。(iii) getCause():此方法将提供来自异常原因的问题消息。但有时,它可能会返回 null。因为对于某些例外情况,可能未指定“原因”。所以这需要包含在 try catch 块中,在这里我们需要使用 getMessage() 方法来获取实际的错误消息。(iv) getClass():此方法将返回实际的异常类名。我们将使用此方法找出异常类名,然后,我们将使用它为不同的异常类提供特定的实现。注意:“getClass()”方法不是来自“Throwable”类。它来自对象类。

您需要创建一个通用方法来处理所有异常,并在所有必需的类中重用此方法。例如:我将该方法命名为“processException”并将其放在“ReusableMethod”类中。

请注意,我在下面的方法(第 8 行)中使用包名称“page”,因为我所有的测试类都放在这个包中。在您的情况下,您需要根据需要更新包名称。此外,我只为两个异常编写了自定义案例:NoSuchElementException 和 AssertionError。您可能需要根据需要编写更多案例。

public void processException(Throwable e) throws Exception {
        StackTraceElement[] arr = e.getStackTrace();
        String className = "";
        String methodName = "";
        int lineNumber = 0;
        for (int i = 0; i < arr.length; i++) {
            String localClassName = arr[i].getClassName();
            if (localClassName.startsWith("page")) {
                className = localClassName;
                methodName = arr[i].getMethodName();
                lineNumber = arr[i].getLineNumber();
                break;
            }
        }
        String cause = "";
        try {
            cause = e.getCause().toString();
        } catch (NullPointerException e1) {
            cause = e.getMessage();
        }
        StackTraceElement st = new StackTraceElement(className, methodName, "Line", lineNumber);
        StackTraceElement[] sArr = { st };
        if (e.getClass().getName().contains("NoSuchElementException")) {
            String processedCause = cause.substring(cause.indexOf("Unable to locate"), cause.indexOf("(Session info: "))
                    .replaceAll("\\n", "");
            Exception ex = new Exception("org.openqa.selenium.NoSuchElementException: " + processedCause);
            ex.setStackTrace(sArr);
            throw ex;
        } else if (e.getClass().getName().contains("AssertionError")) {
            AssertionError ae = new AssertionError(cause);
            ae.setStackTrace(sArr);
            throw ae;
        } else {
            Exception ex = new Exception(e.getClass() + ": " + cause);
            ex.setStackTrace(sArr);
            throw ex;
        }
    }

下面是示例方法,以展示上述方法在测试类方法中的用法。我们通过使用类引用来调用上面创建的方法,在我的例子中是“reuseMethod”。我们将捕获的 Throwable 引用“e”传递给 catch 块中的上述方法:

public void user_Navigates_To_Home_Page() throws Exception {
    try {
            //Certain lines of code as per your tests
            //element.click();
        } catch (Throwable e) {
            reuseMethod.processException(e); 
        }
  }

下面是一些 NoSuchElementException 实现的截图:

在实施此方法之前:

前

实施此方法后:

后

于 2021-01-26T06:57:20.153 回答