該文章主要介紹 testNG(testing next generation,下一代測試技術)框架的使用。
1.首先安裝testNG
2.安裝完成后,創建maven項目,導入TESTNG和selenium依賴。
3.此時就可以直接創建testNG的測試類了
4.下面通過 百度頁面打開、輸入關鍵字、進行搜索,來簡單演示一下testNG的使用

1 package testNGSelenium.testNGDemo; 2 3 import org.testng.annotations.Test; 4 import org.testng.annotations.BeforeTest; 5 import org.testng.annotations.DataProvider; 6 import org.testng.annotations.Parameters; 7 8 import java.util.Date; 9 import java.util.concurrent.TimeUnit; 10 11 import org.apache.bcel.generic.NEW; 12 import org.apache.commons.collections.map.StaticBucketMap; 13 import org.openqa.selenium.By; 14 import org.openqa.selenium.WebDriver; 15 import org.openqa.selenium.WebElement; 16 import org.openqa.selenium.chrome.ChromeDriver; 17 import org.openqa.selenium.support.ui.ExpectedCondition; 18 import org.openqa.selenium.support.ui.WebDriverWait; 19 import org.testng.annotations.AfterTest; 20 21 public class NewTest { 22 //聲明一個全局變量 23 private WebDriver driver; 24 25 26 27 @Test 28 @Parameters({"keyWord"}) 29 public void f(String keywords) { 30 final By input1 = By.id("kw"); 31 final By button1 = By.id("su"); 32 33 //智能等待頁面的輸入框加載出來 34 try { 35 36 (new WebDriverWait(driver, 3)).until(new ExpectedCondition<Boolean>() { 37 38 public Boolean apply(WebDriver input) { 39 WebElement element = input.findElement(input1); 40 System.out.println(new Date()); 41 return element!= null; 42 } 43 }); 44 45 } catch (Exception e) { 46 System.out.println("輸入框3S還沒加載出來!!!"); 47 e.printStackTrace(); 48 } 49 50 51 //智能等待頁面的搜索按鈕加載出來 52 try { 53 (new WebDriverWait(driver, 3)).until(new ExpectedCondition<Boolean>() { 54 55 public Boolean apply(WebDriver input) { 56 WebElement element = input.findElement(button1); 57 System.out.println(new Date()); 58 return element!= null; 59 } 60 }); 61 } catch (Exception e) { 62 System.out.println("搜索按鈕等待了3秒還未加載出來"); 63 e.printStackTrace(); 64 } 65 66 67 driver.findElement(input1).sendKeys(keywords); 68 driver.findElement(button1).click(); 69 70 //等待10S,便於觀察結果 71 try { 72 Thread.sleep(10000); 73 } catch (InterruptedException e) { 74 75 e.printStackTrace(); 76 } 77 78 79 } 80 @BeforeTest 81 public void beforeTest() { 82 driver = new ChromeDriver(); 83 //窗口最大化 84 driver.manage().window().maximize(); 85 86 //加載頁面 87 driver.get("http://www.baidu.com"); 88 89 //設置頁面完全加載時間為3秒,第二個參數TimeUnit.SECONDS是指定時間單位 90 driver.manage().timeouts().pageLoadTimeout(3, TimeUnit.SECONDS); 91 92 } 93 94 @AfterTest 95 public void afterTest() { 96 driver.quit(); 97 } 98 99 }
上面代碼中用到了參數化,是需要在xml文件中設置的:
注意:
1.如果使用了參數化,則必須在XML文件上run as TestNG,否則會提示得不到參數的。
2.運行完成后,我們可以在項目目錄中看到多了一個test-output
對其中的emailable-report.html右鍵---open with---web browser,就可以打開如下的測試報告:
關於配置文件的簡單介紹:
通過上面的配置文件介紹,你可能會問,如果parallelism設置為true,是不是就可以跑多線程了??
是的!!!激不激動,開不開心!這個多線程可以支持我們做兩件事:
1.多個線程來跑同一套件中的不同方法、不同類、不同組件---------------------這樣,當我們的測試代碼很龐大的時候,會非常節省運行時間
2.用來測試多線程同步問題。舉個栗子-----------當有段代碼涉及到:不同線程訪問同一對象,並且會對該對象作出修改的時候,我們就可以針對這段代碼來設計:多個線程同時跑這段代碼,來測試下開發的線程同步是不是已經處理好啦。
下面來介紹下TestNG提供的多線程測試的不同使用方法,為了便於理解,這里使用的都是筆者寫的最簡單的demo:
一:並行的執行某方法
package testNGSelenium.testMethodParallelism; import org.testng.annotations.Test; import org.testng.annotations.BeforeMethod; import org.testng.annotations.AfterMethod; public class MethodParallelismTest { @Test public void f1() { System.out.println("這里是方法1,執行該方法的當前線程ID為"+ Thread.currentThread().getId()); } @Test public void f2() { System.out.println("這里是方法2,執行該方法的當前線程ID為"+ Thread.currentThread().getId()); } @BeforeMethod public void beforeMethod() { System.out.println("這里是before,執行該方法的當前線程ID為"+ Thread.currentThread().getId()); } @AfterMethod public void afterMethod() { System.out.println("這里是after,執行該方法的當前線程ID為"+ Thread.currentThread().getId()); } }
對應修改XML文件為:
該代碼的執行結果為:
二:並行的執行同一套間下同一組件中的不同class
package testNGSelenium.testClassesParallelism; import org.testng.annotations.Test; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterMethod; public class ClassesParallelism1 { @Test public void f() { System.out.println("test1" + Thread.currentThread().getId()); } @BeforeClass public void beforeClass() { System.out.println("beforeClass1" + Thread.currentThread().getId()); } @AfterClass public void afterClass() { System.out.println("afterClass2" + Thread.currentThread().getId()); } }
package testNGSelenium.testClassesParallelism; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class ClassesParallelism2 { @Test public void f() { System.out.println("test2" + Thread.currentThread().getId()); } @BeforeClass public void beforeClass() { System.out.println("beforeClass2" + Thread.currentThread().getId()); } @AfterClass public void afterClass() { System.out.println("afterClass2" + Thread.currentThread().getId()); } }
對應XML的設置:
該代碼的執行結果為:
三:同一套間中的不同組件並行
package testOneSuitTwoTest; import org.testng.annotations.Test; import org.testng.annotations.BeforeMethod; import org.testng.annotations.AfterMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Parameters; import org.testng.annotations.BeforeClass; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeTest; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeSuite; import org.testng.annotations.AfterSuite; public class OneSuitTwoModuleTest { @Test @Parameters({"location"}) public void f(String p) { System.out.println(p); System.out.println("Test---thread" + Thread.currentThread().getId()); } @BeforeMethod public void beforeMethod() { System.out.println("beforeMethod---thread" + Thread.currentThread().getId()); } @AfterMethod public void afterMethod() { System.out.println("afterMethod---thread" + Thread.currentThread().getId()); } /* @DataProvider public Object[][] dp() { return new Object[][] { new Object[] { 1, "a" }, new Object[] { 2, "b" }, }; }*/ @BeforeClass public void beforeClass() { System.out.println("beforeClass---thread" + Thread.currentThread().getId()); } @AfterClass public void afterClass() { System.out.println("afterClass---thread" + Thread.currentThread().getId()); } @BeforeTest public void beforeTest() { System.out.println("beforeTest---thread" + Thread.currentThread().getId()); } @AfterTest public void afterTest() { System.out.println("afterTest---thread" + Thread.currentThread().getId()); } @BeforeSuite public void beforeSuite() { System.out.println("beforeSuite---thread" + Thread.currentThread().getId()); } @AfterSuite public void afterSuite() { System.out.println("afterSuite---thread" + Thread.currentThread().getId()); } }
對應的XML設置為:
上面代碼的執行結果為;
四:多線程執行某方法
package testNGSelenium.moreThreadTest; import org.testng.annotations.Test; import org.testng.annotations.BeforeTest; import org.testng.annotations.AfterTest; public class MoreThreadTest { //這里代表 啟動三個線程,該方法總共執行9遍,設置整個測試方法的超時時間為2S @Test(threadPoolSize=3,invocationCount=9,timeOut=2000) public void f() { System.out.println("Test---threadId:"+Thread.currentThread().getId()); } @BeforeTest public void beforeTest() { } @AfterTest public void afterTest() { } }
對應的XML文件並沒有特別設置啥參數。
執行結果為:
注意點:
1.如果有童鞋在運行TESTNG套件的時候,遇到了ElementTravelsal找不到的問題,則在自己的pom.xml文件中引入依賴包:xml-apis
<!-- https://mvnrepository.com/artifact/xml-apis/xml-apis -->
<dependency>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.4.01</version>
</dependency>
2.如果遇到運行程序之后,在console窗口遇到了亂碼:
請打開eclipse.ini文件,並添加: -Dfile.encoding=UTF-8
3.一個xml中間,只能有一個suite標簽;
一個suite可以有多個test,test名稱必須不同(否則報錯:Two tests in the same suite cannot have the same name);
一個test中間可以包含多個class,
一個class里面可以包含多個方法
4.在testNg的 suite file中,添加上
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
相當於標簽控制,只有合法標簽才能輸入。否則報錯。
5.如果讀者使用的開發工具是IDEA,那么久不需要安裝testNG的插件了。IDEA是自帶了testNG的插件的。只要在maven中添加testNg的包就可以了。
6.老的版本中
<suite name="suitname1" parallel="true" thread-count="2">
parallel的值是沒有“true”的。
分為tests,classes,methods級別
tests:不同test tag下的用例可以在不同的線程執行,相同test tag下的用例只能在同一個線程中執行
classes:不同class tag下的用例可以在不同的線程執行,相同class tag下的用例只能在同一個線程中執行。
methods:所有用例都可以在不同的線程去執行。
7.關於dataprovider的並發
https://www.cnblogs.com/znicy/p/6534893.html