# Testing ###### tags: `eGroupAI 開發規範` > 測試用意不是來證明你是對的,而是你沒有錯。 --- > 參考資料 - [開源框架:JUnit Gossip - OpenHome.cc](http://openhome.cc/Gossip/JUnit/index.html) - [JUnit介紹,JUnit是什麼?](http://tw.gitbook.net/junit/what-is-junit.html#) ## JUnit單元測試 > 簡介 - JUnit是個單元測試(Unit test)框架 - 單元測試指的是測試一個工作單元(a unit of work)的行為e.g. 建築橋墩:一個螺絲釘、一根鋼筋、一條鋼索、一公斤的水泥,都可謂是一個工作單元。 - 單元之間獨立 > Basic Annotations 常用註解 - @Test:表示要執行此區段裡的測試碼 - @Test(expected = Exception.class): 預期會拋出Exception.class的異常(e.g. 算術異常ArithmeticException) - @Test(timeout = 100):測試方法預期執行不超過100**毫秒** - @Before:每次測試前執行 - @After: 每次測試後執行 - @BeforeClass:在開始第一個測試前執行,只執行一次,必須為static void - @AfterClass :全部測試完畢後執行,只執行一次,必須為static void - @Ignore("忽略原因可以寫在這"):忽略測試,測試方法不會被執行 - @Runwith:運行器(Runner)執行之類別,可進行更改 - @Parameters:測試用參數宣告 > 上述範例 ```java import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; public class BeforeAndAfterTest { @BeforeClass public static void beforeClass() { System.out.println("BeforeClass"); } @AfterClass public static void afterClass() { System.out.println("AfterClass"); } @Before public void before() { System.out.println("Before"); } @After public void after() { System.out.println("After"); } @Test public void test01() { System.out.println("Test01"); } @Test public void test02() { System.out.println("Test02"); } } ``` 執行結果: ```java BeforeClass Before Test01 After Before Test02 After AfterClass ``` **注意:1.所有測試方法必須使用public2.@BeforeClass與@AfterClass必須使用static void** ## 基本驗證 > JUnit 提供的 Assert 驗證方法 ### **assertEquals** - 值可能是類型有 int, short, long, byte, char or java.lang.Object - 查看物件中存的值是否是期待的值,預期值(expected)=實際值(actual) ``` void assertEquals([String message], expected value, actual value) //範例 assertEquals(expected, new Caculate().add(input1, input2)); ``` ### **assertTrue、assertFalse** - boolan值 - 查看變數是是否為false或true ``` void assertTrue([String message], boolean condition) void assertFalse([String message],boolean condition) //範例 assertTrue(expected, new Member().isLogin(input)); assertFalse(expected, new Member().isLogin(input)); ``` ### **assertNull、assertNotNull** - 用來查看物件是否為空和不為空 ``` void assertNull([String message], java.lang.Object object) void assertNotNull([String message], java.lang.Object object) //範例 @Test public void sample_assert_null(){ //arrange Object expectNull = null; Object expectNotNull = new Object(); //assert Assert.assertNull(expectNull); Assert.assertNotNull(expectNotNull); } ``` ### **assertSame、assertNotSame** - 用來比較兩個物件的引用是否相等和不相等 ``` void assertSame([String message], java.lang.Object expected, java.lang.Object actual) void assertNotSame([String message], java.lang.Object unexpected, java.lang.Object actual) /*範例 *same 跟 equals 的差別其實就是平常使用 a == b 跟 a.equals(b) 是一樣的,看下面例子就可以了解 */ @Test public void sample_assert_same(){ //arrange Object expect = new Object(); Object expectNotSame = new Object(); Object actual = expect; //assert Assert.assertSame(expect, actual); Assert.assertNotSame(expectNotSame, actual); } ``` ### **assertArrayEquals** - 用來比較預期數組和結果數組相等 ``` void assertArrayEquals([String message], expectedArray, resultArray) //範例 @Test public void sample_assert_array(){ int[] expect = new int[]{1, 2, 3}; int[] actual = new int[]{1, 2, 3}; Assert.assertArrayEquals(expect, actual); } ``` ### **驗證集合** ``` //範例 @Test public void sample_assert_collection(){ List<Integer> expect = Arrays.asList(1, 2, 3); List<Integer> actual = Arrays.asList(1, 2, 3); Assert.assertEquals(expect, actual); } ``` ## 撰寫第一個測試 > 起手式 先把JUnit框架引入 - 專案右鍵->Build Path->Libraries->AddLibrary - 選擇JUnit4 - 在src/test/java 路徑下新增測試程式 - 右鍵新增Junit 測試檔案 - 在測試檔案上,右鍵->Run As->Junit Test,即可進行Junit 測試。 > 測試檔案命名方式 模組名稱或要被測試類別的名稱+Test ```java //e.g. 如果模組為:Caculate,模組測試則是CaculateTest //模組 public class Caculate { public int add(int a,int b){ return a+b; } public int subtract(int a,int b){ return a-b; } public int multiply(int a,int b){ return a*b; } public int divide(int a,int b){ return a/b; } } //模組測試 public class CaculateTest { @Test public void testAdd() { assertEquals(3, new Caculate().add(2, 1)); } @Test public void testSubtract() { assertEquals(8, new Caculate().subtract(9, 1)); } @Test public void testMultiply() { assertEquals(6, new Caculate().multiply(3, 2)); } @Test public void testDivide() { assertEquals(3, new Caculate().divide(9, 3)); } @Ignore("可以在這說明忽略原因") @Test(timeout=2000) public void testWhile(){ while (true) { System.out.println("run forever"); } } @Test(timeout=2000) public void readFile(){ try { Thread.sleep(2000); } catch (Exception e) { // TODO: handle exception } } } ``` 由上述模組測試範例,可以看到其中一個測試方法,以testAdd()為例 ```java //assertEquals(預期值, 測試值(可以method回傳)); @Test public void testAdd() { assertEquals(3, new Caculate().add(2, 1)); } ``` 當預期值=測試值,代表其測試通過,反之,不通過。 > 參數化測試 - 使用多組數值進行測試 ```java /* *1.更改默認的測試運行器Runner,@RunWith(Parameterized.class) *2.宣告變量來存放預設值跟結果值 *3.宣告一個返回值為Collection的公共靜態方法,並使用@Parameters進行修飾 */ @RunWith(Parameterized.class) public class ParameterTest { int expected=0; int input1=0; int input2=0; @Parameters public static Collection<Object[]> t(){ return Arrays.asList(new Object[][]{ {3,2,1}, {5,2,3}, {6,2,4} }); } public ParameterTest(int expected,int input1,int input2){ this.expected=expected; this.input1=input1; this.input2=input2; } @Test public void testAdd(){ assertEquals(expected, new Caculate().add(input1, input2)); } ``` > 測試套件 Suite - 批量運行,把所有測試方法集何在一個測試套件中,只須執行該套件一次即可。 ```java /* *1.同時去執行SuiteClasses中的所有測試類 *2.寫一個作為測試套件的入口類,這個類別裡面不包含其他方法 *3.更改默認的測試運行器Runner,@RunWith(Suite.class) *4.將要測試之類別,傳到Suite.SuiteClasses({}) */ @RunWith(Suite.class) @Suite.SuiteClasses({ TaskTest1.class, TaskTest2.class, ParameterTest.class, Amount2RMBTest.class, CaseIDGeneratorTest.class }) public class SuiteTest { } ``` - 也能直接產生Suite測試套件 右鍵->新增 JUnit Test Suite->選擇勾選測試類 ![https://laitaiyuan1.gitbooks.io/egroup/content/ssss.PNG](https://laitaiyuan1.gitbooks.io/egroup/content/ssss.PNG) > 測試慣例 - 軟體運作良好的事物都是經過測試檢驗的。 - 測試一點點,程式碼寫一點點,測試一點點,程式碼寫一點點...... - 確認所有測試都能100%通過。 - 要測試的程式碼是最可能錯誤的區域。 - 撰寫程式碼之前先寫單元測試 - 程式功能模組化 ## 壓力測試 ### **Jmeter** 下載 [http://jmeter.apache.org/download_jmeter.cgi](http://jmeter.apache.org/download_jmeter.cgi) 教學 [http://cloudchen.logdown.com/posts/247932/apache-jmeter-tool-for-load-test-and-measure-performance](http://cloudchen.logdown.com/posts/247932/apache-jmeter-tool-for-load-test-and-measure-performance)