【问题标题】:Fail testNG @Test before assertion is evaluated在评估断言之前失败 testNG @Test
【发布时间】:2017-01-04 07:03:29
【问题描述】:

如果在测试运行期间任何测试步骤抛出异常(例如 NoSuchElementException),我希望 testNG 测试 (@Test) 失败。 (仅举例)

在当前场景中,我正在检查是否单击特定任务,然后一些文本会出现在 UI 上的元素中。但是最近 AUT 在单击任务时引发了网络错误,因此包含我正在验证的文本的元素没有出现在 UI 上。所以 webdriver 抛出了 NoSuchElementException。但由于我所有的断言都在测试步骤的后期某处,TestNG 将此测试标记为通过,因此也继续执行相关的测试用例。

如果测试中的所有步骤都没有执行或抛出任何异常,有没有办法让测试失败?

这里是示例代码:

public class DummyTest {

@Test
public void testThis(){
    try{
        testThisSteps();
    }catch(Exception e){
        e.printStackTrace();
    }
}

public void testThisSteps() throws Exception{
    System.setProperty("webdriver.chrome.driver","C:\\chromedriver.exe");
    WebDriver driver = new ChromeDriver();
    driver.get("http://toolsqa.com/automation-practice-form/");
    driver.manage().window().maximize();
    driver.findElement(By.xpath("//h1[text()='Practice Automation']"));
    int i = driver.findElements(By.name("firstname")).size();
    Assert.assertTrue(i!=0,"Element does not exist even though page is loaded");
  }
}

现在的问题是,如果 webdriver 在这种情况下无法找到元素,我故意在最大化代码后遗漏了一些文本,它将抛出 NoSuchElementExeception 并且不会执行进一步的代码,这导致断言没有得到评估和测试用例依赖于执行的进一步测试用例停止执行。下面是执行结果:-

org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"xpath","selector":"//h1[text()='Practice Automation']"}

*** 元素信息:{Using=xpath, value=//h1[text()='Practice Automation']

默认套件

运行的测试总数:1,失败:0,跳过:0

进程以退出代码 0 结束

【问题讨论】:

  • 如果出现一些错误,如果测试没有意义,就会自发地发出声音。 @beforetest 会是一个解决方案吗?如果 beforetest 方法失败,这将跳过测试。
  • 您可以在testng 测试中的任何时候抛出异常。
  • 1.不要将您的测试代码放在try-exceptblock 下,这样会引发异常并交给TestNG。然后TestNG可以将其标记为测试中的错误。 2. 重新审视你的断言,尽管网络错误,但它正在成功(断言通过,我觉得很可疑)。
  • @Naveen 实际上问题是断言没有得到完全评估,因为我提到我的断言在测试步骤的后面部分,并且这些步骤被跳过,因为我期待一个带有特定文本的 webelement抛出 NoSuchElementException 并且 testNG 继续执行测试套件中的下一个测试用例。
  • 那么,那个测试方法发生了什么?标记为通过/失败/错误?请分享测试方法代码。

标签: java selenium selenium-webdriver webdriver testng


【解决方案1】:

我怀疑测试中的代码被try-catch 块包围。如果在方法定义中添加throws Exception 而没有try-except,则当除Assertions 之外抛出任何异常时,您可以获得标记为Fail 的测试方法的行为,而不是Pass。

我尝试了以下代码,它抛出了NoSuchElementException(模拟你的问题):

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.Assert;
import org.testng.annotations.Test;

import org.testng.annotations.Test;
import org.testng.asserts.Assertion;

public class SeleniumTests {


    @Test()
    public void testmethod() throws  Exception{
        WebDriver driver = new ChromeDriver();
        driver.get("http://www.google.com");
        driver.findElement(By.className("something")); // throws NoSuchElementException
        Assert.assertEquals(true, false);
        driver.quit();
    }

}

这里,由于类名为"something" 的元素不存在,因此抛出NoSuchElementException。

Assert.assertEquals 未执行。

TestNG 将其标记为Failed。这是您期望的行为吗?

以下是完整的日志:

[TestNG] Running:
  C:\Users\USER_HP_2013_03\AppData\Local\Temp\testng-eclipse--1064112655\testng-customsuite.xml

Starting ChromeDriver 2.25.426923 (0390b88869384d6eb0d5d09729679f934aab9eed) on port 10078
Only local connections are allowed.
Jan 04, 2017 5:10:03 PM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Attempting bi-dialect session, assuming Postel's Law holds true on the remote end
log4j:WARN No appenders could be found for logger (org.apache.http.client.protocol.RequestAddCookies).
log4j:WARN Please initialize the log4j system properly.
Jan 04, 2017 5:10:06 PM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: OSS
FAILED: testmethod
org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"class name","selector":"something"}
  (Session info: chrome=55.0.2883.87)
  (Driver info: chromedriver=2.25.426923 (0390b88869384d6eb0d5d09729679f934aab9eed),platform=Windows NT 6.1.7601 SP1 x86_64) (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 42 milliseconds
For documentation on this error, please visit: http://seleniumhq.org/exceptions/no_such_element.html
Build info: version: '3.0.1', revision: '1969d75', time: '2016-10-18 09:48:19 -0700'
System info: host: 'HP201303', ip: '192.168.56.1', os.name: 'Windows 7', os.arch: 'amd64', os.version: '6.1', java.version: '1.8.0_73'
Driver info: org.openqa.selenium.chrome.ChromeDriver
Capabilities [{applicationCacheEnabled=false, rotatable=false, mobileEmulationEnabled=false, networkConnectionEnabled=false, chrome={chromedriverVersion=2.25.426923 (0390b88869384d6eb0d5d09729679f934aab9eed), userDataDir=C:\Users\USER_H~1\AppData\Local\Temp\scoped_dir5260_26036}, takesHeapSnapshot=true, pageLoadStrategy=normal, databaseEnabled=false, handlesAlerts=true, hasTouchScreen=false, version=55.0.2883.87, platform=XP, browserConnectionEnabled=false, nativeEvents=true, acceptSslCerts=true, locationContextEnabled=true, webStorageEnabled=true, browserName=chrome, takesScreenshot=true, javascriptEnabled=true, cssSelectorsEnabled=true}]
Session ID: 92cbb27a874d7d2215eee51fc6a77819
*** Element info: {Using=class name, value=something}
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
    at java.lang.reflect.Constructor.newInstance(Unknown Source)
    at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:216)
    at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:168)
    at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:635)
    at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:368)
    at org.openqa.selenium.remote.RemoteWebDriver.findElementByClassName(RemoteWebDriver.java:457)
    at org.openqa.selenium.By$ByClassName.findElement(By.java:391)
    at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:360)
    at SeleniumTests.testmethod(SeleniumTests.java:14)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
    at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
    at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
    at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
    at org.testng.TestRunner.privateRun(TestRunner.java:767)
    at org.testng.TestRunner.run(TestRunner.java:617)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
    at org.testng.SuiteRunner.run(SuiteRunner.java:240)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)
    at org.testng.TestNG.run(TestNG.java:1057)
    at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:132)
    at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:236)
    at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:81)


===============================================
    Default test
    Tests run: 1, Failures: 1, Skips: 0
===============================================


===============================================
Default suite
Total tests run: 1, Failures: 1, Skips: 0
===============================================

[TestNG] Time taken by org.testng.reporters.JUnitReportReporter@35bbe5e8: 9 ms
[TestNG] Time taken by org.testng.reporters.SuiteHTMLReporter@2a18f23c: 12 ms
[TestNG] Time taken by org.testng.reporters.jq.Main@4ec6a292: 27 ms
[TestNG] Time taken by org.testng.reporters.EmailableReporter2@3f0ee7cb: 9 ms
[TestNG] Time taken by [FailedReporter passed=0 failed=0 skipped=0]: 4 ms
[TestNG] Time taken by org.testng.reporters.XMLReporter@66d33a: 8 ms

【讨论】:

  • 让我试试这个。无论如何,我已经编辑了问题,我认为您已经纠正了我所面临的问题。
【解决方案2】:

这个问题实际上取决于 OP 所要求的行为。

您的选择是: a) 对未能出现在 UI 上的元素添加另一个断言 (可能不理想,因为您想验证给定原因而不是单个元素的测试,即成功登录而不是“单击登录按钮”

b) 使用 testng 注释来控制流程和所需行为dependsOnMethods="yourMethodContainingTheElementThatOccassionallyAppears"

c) 避免捕获异常,因此 testng 将失败该步骤(如果您还使用解决方案 (b),则将跳过其余测试(以黄色表示)

d) 捕获 SeleniumNoEmentException,然后在 try/catch 块中对 elementPresent 进行断言。通过相应地调整依赖关系,您可以决定是要保留脚本还是跳过其余步骤。

e) 使用 softAssertion(意味着如果该元素以后不再出现,您的测试不会失败,但会继续运行其余步骤

希望这会有所帮助!

【讨论】:

  • 实际上,我正在寻找的是如果任何测试步骤引发异常,则使测试用例失败的机制。我已经使用过dependsOnMethods、dependsOnGroups、softAssertions等。对于您建议的选项a),这将特别适用于该语句,但我正在寻找一种解决方案,如果任何测试步骤失败,则将测试标记为失败(抛出异常),无论该特定步骤是否是断言。
  • 但这是标准的 testNG 行为(即,如果一个步骤失败,则整个测试用例被标记为失败)。也许分享一些代码会有所帮助! :) 我猜您已经在代码中使用了某种形式的 try/catch,并且您正在捕获异常,这就是您的测试被标记为通过的原因..
【解决方案3】:

试试这个:

try {
    driver.findElement(by.xpath("//h1[text()='Practice Automation']");
}catch (org.openqa.selenium.NoSuchElementException e){
     assert.fail("the element I was attempting to location was not found.");
}

这是一种廉价的hacky方式来做你正在尝试的事情,但它会起作用并且会触发一个断言。

你的 try catch 块也是测试没有失败的原因。您正在通过捕获它来处理测试中的失败

try{
    testThisSteps();
}catch(Exception e){
    // you caught the failure. No error will pop up because it was caught
    e.printStackTrace();
}

抓住你实际上是在迫使测试通过。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-31
    • 1970-01-01
    • 1970-01-01
    • 2022-12-22
    • 1970-01-01
    • 2011-01-03
    • 1970-01-01
    相关资源
    最近更新 更多