suit -> class -> method,包含before和after兩種形式,恰好對應各階段的初始化(setup)和清理(teardown)java
另外test 和 groups能夠定義不一樣的組合,好比指定某個功能模塊(package),或者以提測版本號將測試類/方法分組web
import org.testng.Assert; import org.testng.annotations.*; public class App { private void log(String action) { final String FORMATTER = "===== %-20s ====="; System.out.println(String.format(FORMATTER, action)); } @BeforeSuite public void beforeSuit() { log("before suit"); } @AfterSuite public void afterSuit() { log("after suit"); } @BeforeClass public void beforeClass() { log("before class"); } @AfterClass public void afterClass() { log("after class"); } @BeforeMethod public void beforeMethod() { log("before method"); } @AfterMethod public void afterMethod() { log("after method"); } @Test public void testAdd() { log("test add"); Assert.assertEquals(4, 1 + 3); } } --------------------------------------------------- ===== before suit ===== ===== before class ===== ===== before method ===== ===== test add ===== ===== after method ===== ===== after class ===== ===== after suit =====
另外,除了@Test註解能夠出現屢次外,before/after + suit/test/class/method等也能夠出現屢次,不過貌似沒多大意義oracle
測試方法是否生效,默認爲true;若是不但願執行,能夠置爲falseapp
@Test(enabled = false)
測試方法的上游依賴,若是依賴的對象執行失敗,則該測試方法不執行(skip)框架
public class App { private void log(String action) { final String FORMATTER = "===== %-20s ====="; System.out.println(String.format(FORMATTER, action)); } @Test(dependsOnMethods = {"upMethod"}) public void downMethod() { log("run down method"); Assert.assertEquals(2, 1+1); } @Test public void upMethod() { log("run up method"); Assert.assertEquals(3, 5/3); } } ------------------------------------------------ =============================================== Default Suite Total tests run: 2, Failures: 1, Skips: 1 ==============================================
Assert沒法實現異常的校驗,但沒法避免異常的發生,或者但願人爲地拋出異常,所以須要藉助此參數curl
public class App { @Test(expectedExceptions = {java.lang.ArithmeticException.class}) public void testExcption() { int a = 5 / 0; } }
方法引用的測試數據,避免同一個方法書寫屢次,能夠設計爲數據驅動ide
public class App { @DataProvider(name = "data") public Object[][] data() { return new Object[][] { {1, 1}, {2, 4}, {3, 9}, }; } @Test(dataProvider = "data") public void testSquare(int num, int expected) { int result = num * num; Assert.assertEquals(result, expected); } }
測試方法的數據提供者,必須返回Object[][]
對象測試
包含2個參數:ui
測試方法查找指定的dataProvider時,默認是當前類及其父類url
若是數據由其餘類提供,則需指定dataProviderClass,而且由@DataProvider註解的方法必須爲static
public class App { @Test(dataProvider = "data", dataProviderClass = DataDriver.class) public void testSquare(int num, int expected) throws InterruptedException { int result = num * num; Assert.assertEquals(result, expected); } } class DataDriver { @DataProvider(name = "data", parallel = true) public static Object[][] data() { return new Object[][] { {1, 1}, {2, 4}, {3, 9}, }; } }
多個測試方法能夠指定同一個DataProvider
DataProvider支持將Method做爲第一個參數,根據不一樣的方法讀取不一樣的數據文件,如Excel、Txt
public class App { @Test(dataProvider = "dp", dataProviderClass = DataDriver.class) public void test_1(String arg) { System.out.println("== run test-1"); Assert.assertTrue(arg != null); } @Test(dataProvider = "dp", dataProviderClass = DataDriver.class) public void test_2(String arg) { System.out.println("== run test-2"); Assert.assertTrue(arg != null); } } class DataDriver { @DataProvider(name = "dp") public static Object[][] data(Method method) { System.out.println(method.getName()); return new Object[][]{ {"java"}, }; } } ---------------------------------------------------- test_1 == run test-1 test_2 == run test-2
加載環境變量
好比在初始化時,根據提供的參數區分開發環境與測試環境
@Parameters(value = {"jdbcUrl"}) @BeforeSuite public void initSuit(String jdbcUrl) { String jdbcurl = jdbcUrl; }
那麼parameter的值在哪設置呢? ——testng.xml
<suite name="Mysuite"> <parameter name="jdbcUrl" value="jdbc:oracle:thin:@oraHost:1522:orcl"/> <test name="Mytest"> ...
固然與jenkins結合會更妙
Parameters are scoped. In testng.xml, you can declare them either under a <suite> tag or under <test>. If two parameters have the same name, it's the one defined in <test> that has precedence. This is convenient if you need to specify a parameter applicable to all your tests and override its value only for certain tests.*test標籤下的參數優先級高於suit
動態建立測試類
拿官網例子來說:編寫一個方法實現屢次訪問同一網頁
// 官網使用了parameter,而後須要在testng.xml中配置多個參數值,實屬麻煩 public class TestWebServer { @Test(parameters = { "number-of-times" }) public void accessPage(int numberOfTimes) { while (numberOfTimes-- > 0) { // access the web page } } }
那麼使用@Factory將簡化配置
public class WebTest { private int m_numberOfTimes; public WebTest(int numberOfTimes) { m_numberOfTimes = numberOfTimes; } @Test public void testServer() { for (int i = 0; i < m_numberOfTimes; i++) { // access the web page } } } ----------------------------------------------------- public class WebTestFactory { @Factory public Object[] createInstances() { Object[] result = new Object[10]; for (int i = 0; i < 10; i++) { result[i] = new WebTest(i * 10); } return result; } }
經過@Factory動態建立測試類,返回Object[]
對象 —— 包含一組測試類實例,框架會自動運行每一個實例下的測試方法
不過,雖然簡化了配置,但並非指不用配置,須要在testng.xml中指定工廠類
<suite name="Suite1" verbose="1" > <test name="Test1"> <classes> <class name="WebTestFactory" /> <class name="WebTest" /> </classes> </test> </suite>
可是細想一下,測試方法的參數化能夠經過@DataProvider實現
我理解的兩者區別以下:
應用於測試類,忽略該類下全部的測試方法
至關於@Test(enabled=false),不過是批量的