【问题标题】:How to use a single catch block for both TestNG assertion errors and RunTime exceptions如何对 TestNG 断言错误和运行时异常使用单个 catch 块
【发布时间】:2017-05-19 14:00:28
【问题描述】:

我会尽量提供尽可能多的信息。 我正在使用带有 Java.+Selenium 的 TestNG 框架 以下是我编写的 2 个自定义方法。

// Checks if a WebElement is present on the screen
public boolean isElementPresent(WebElement element) {
    try {
        element.isDisplayed();
        return true;
    } catch (RuntimeException e) {
        return false;`
    }
}


// Used to click on the desired element
public void clickWebElement(WebElement element) {
    isElementPresent(element);
    element.click();
}


protected void enterDataintoField(WebElement element,String fieldData) {
    isElementPresent(element);
    element.click();
    element.clear();
    element.sendKeys(fieldData);    
}

现在假设有一个链接说登录。点击登录会打开一个页面,其中包含用户名和密码 2 个字段。下面的代码用于登录。(登录名、用户名、密码和 logoutBtn 是 webElements)

  public void login(String username, String password)
 {
 try{
 clickWebElement(Login);
 //pause few seconds for page load
 enterDataintoField(username, "Adam");
 enterDataintoField(password, "mypassword");
 //pause few seconds to login
 Assert.assertTrue(isElementPresent(logoutBtn));
 }catch({**ErrorType**} e){
 //Some code here
 }
}

现在是我的问题。如果我在上面的 catch 块中将 ErrorType 设置为 RuntimeException 则如果出现任何问题,例如未显示用户名字段或缺少登录按钮,那么这个 catch 块将能够抓住问题。但是这个 catch 块将无法捕获上面验证登录是否成功的 Assert 语句。

类似地,如果我使用上面的 AssertionError,那么 catch 块将能够捕获断言失败但无法捕获任何其他问题的场景。 因此,我需要一些关于我可以在这里做什么的建议。 我有数千行代码,所以 我不想在任何地方同时使用 RuntimeException 和 AssertionError 捕获块(如 2 个捕获块。我想要一个捕获块)

非常感谢任何其他建议或最佳实践。

【问题讨论】:

  • 我的问题不一定在这一件事上。如果有更好的方法来使用 testng 做同样的事情,请不要犹豫。
  • 你能详细说明你在 catch 块中做了什么吗?在测试场景中,通常仅当您想要断言异常本身时才需要捕获异常。例如,它是否是正确的异常类型,是您需要处理异常的数据集...
  • 你的逻辑有缺陷。 isElementPresent 返回一个布尔值,但您并未对该结果采取行动,因此如果该元素不存在,它会从 try/catch 中返回 false,但由于您是从其他方法调用它,因此忽略结果并继续。应该更像 if (isElementPresent(element)) element.click();
  • 不要那样做。以不同的方式捕获每个不同的事物,并且根本不捕获测试断言错误。断言错误是Error 类型,并不意味着被测试本身捕获,而是传递给测试报告机制。
  • 详细说明。一旦我像示例 Assert.assertTrue(isElementPresent(logoutBtn));我立即调用像这样的“通过”报告方法“report.pass(“这一步通过”);而在 catch 块中,我有一个像这样的“失败”报告方法“report.fail(“这一步失败”); .因此,如果断言条件为真,它将转到报告传递,如果失败,它将转到调用报告失败的 catch 块

标签: java selenium testng


【解决方案1】:

您的 catch 块仅捕获扩展 java.lang.ExceptionAssertionErrorThrowable 对象是一个错误(因为它扩展了 java.lang.Error)但是,如果您真的想捕获 AssertionError在 catch 块中 - 您需要使用以下 catch 块语法:

catch (AssertionError e) { ... }

所以这意味着 您不能在同一个 catch 块中同时处理异常和错误; 但是您可以尝试使用两个单独的 catch 块,一个用于处理异常,另一个用于处理如下错误:

    try{

    }catch(Exception e){
      ...
    }
    catch(AssertionError e){
      ...   
    }

【讨论】:

  • 我知道这是可能的,但正如我在最初的帖子中提到的,这正是我想要避免的。我也不一定需要 AssertionError 的 catch 块。我真正想要的是检查像 Assert.assertTrue(isElementPresent(logoutBtn)); 这样的条件如果它失败了,我想调用一些方法。
  • 如果你不一定需要处理 AssertionError,你可以在你的方法签名中使用 throws AssertionError,其余的可以在独立的 try/catch 块中处理
【解决方案2】:

这是您问题的答案:

你需要在这里解决很多事情如下:

  1. 您已将isElementPresent(WebElement element) 定义为返回boolean,但是当您调用isElementPresent(element); 时,您根本没有使用返回boolean 状态。所以我的做法是检查for 循环中的boolean 状态,然后继续进行element.click();
  2. Assert.assertTrue 的实现在此处与Assert.assertTrue(isElementPresent(logoutBtn)); 不正确。 来自TestNGAssertions 旨在验证@Test 结果。这些结果是您和您的组织可能想要跟踪的信息。永远不要在try 块中写入Assertions,只是为了捕获Catch 块中的失败断言并强制将它们转换为状态Pass
  3. 要了解try/catchAssertions 之间的关系,您可以考虑查看此discussion
  4. 在您的代码中,您尝试将Assert 的存在Logout 按钮设置为Assert.assertTrue(isElementPresent(logoutBtn));。那不应该是一个断言。相反,您可以诱导ImplicitlyWaitExplicitWait 使Logout 按钮可点击。
  5. 现在,您要寻找的答案是Where and How do you implement Assertions?Assertions 肯定会被写出try 块。断言可以应用于页面上的Page TitlePage Source 或任何Element。根据最佳实践,有两种实现断言的方法。第一个,断言可以是您的Test 类的一部分。第二个,根据 POM 中的 PageFactory,断言应该在单独的包/类中处理。您需要调用包含断言的类的方法。
  6. 如果您想在您的代码中添加任何断言,您可以在打开预期的 URL 时首先添加它,然后您可以在登录到验证 Page Title 的 Web 应用程序后再添加一个断言。

如果这能回答您的问题,请告诉我。

【讨论】:

    【解决方案3】:

    所有这些断言/验证和等待相关的实现都应该由底层自动化框架提供。您可以使用一种可用的高效自动化框架,例如QAF。您的实现可能如下所示:

    // Checks if a WebElement is present on the screen
    element.isPresent()
    // verify  WebElement is present on the screen
    element.verifyPresent()
    // assert  WebElement is present on the screen
    element.assertPresent()
    
    //actions and other element methods no need to wait
    element.click();
    

    它还预定义了您可以使用的step library。在这种情况下,您的登录信息可能如下所示:

    public void login(String username, String pwd){
        //loc provided in locator file
        sendKeys(username, "username.txt.loc");
        sendKeys(text, "password.txt.loc");
        click("login.btn.loc");
    }
    

    如果你想使用 BDD

    When send keys 'my text' to 'username.loc' 
    And send keys 'my text' to 'password.loc' 
    And click on 'login.loc'
    They verify 'welcome.msg.loc' is present
    

    您可以参考qaf-step-by-step-tutorial

    【讨论】:

      【解决方案4】:

      弄清楚我需要做什么。 我写了一个自定义断言方法:

      public void myAssertTrue(Boolean condition){
          try {
              Assert.assertTrue(condition);
          } catch (AssertionError e) {
              e.printStackTrace();
              throw new RuntimeException();
          }
      }
      

      修改了isElementPresent方法:

      // Checks if a WebElement is present on the screen
      public void isElementPresent(WebElement element) {
          try {
              element.isDisplayed();
          } catch (RuntimeException e) {
              throw e;
          }
      }
      

      通过这 2 个更改,我可以使用 RuntimeException 捕获块来捕获运行时和资产错误

      【讨论】:

        猜你喜欢
        • 2015-06-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-06
        • 2021-04-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多