unittest.TestCase中測試用例執行順序問題
我們在做自動化測試用例的時候,通常會把一個個測試用例放到一個unittest.TestCase的擴充套件類中,當我們執行測試用例檔案時,測試檔案中的測試用例會隨機執行的。如:
#-*- coding: UTF-8 -*-
import time
import unittest
import sys
class DemoTest(unittest.TestCase):
def setUp(self):
….
Def test_a(self):
………
Def test_b(self):
………
Def test_c(self):
………
Def test_d(self):
………
Def tearDown(self):
………
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(DemoTest)
unittest.TextTestRunner(verbosity=2).run(suite)
上面的示例是包含四個測試用例的一個測試用例集,在我們執行這個測試檔案後,四個測試用例的執行順序是隨機的。如果這幾個測試用例有依賴關係,則會影響你們用例的執行,於是我在想能不能控制一下測試用例的執行順序呢?雖然測試用例相互之間不能有依賴關係,可是這算是一個嘗試吧!我在網上查到一個方法,是適用於junit的:
換種順序來執行TestCase(Junit適用)
Junit的TestCase,總是按固定的順序執行的. 正如你在Eclipse中跑Run As Junit Test, 無論你跑多少次, TestCase的執行順序都是一致的,可重複的. 這就導致一個問題, TestCase之間的獨立性無法保證.
例如下面一個Test類中的2個TestCase:
public class DaoTest {
@Test
public void test_count() {
dao.insert(new User("root", "123456"));
assertEquals(1, dao.count(User.class));
}
@Test
public void test_insert() {
dao.clear(User.class, null);
dao.insert(new User("admin", "123456"));
assertEquals(1, dao.count(User.class));
}
}
如果先執行test_count()然後執行test_insert(),兩個TestCase都能通過.
但如果先執行test_insert(),然後執行test_count(),則test_count()會失敗.
所以,有必要去打亂TestCase的預設執行順序,以暴露出TestCase本身的問題. TestCase更可靠,才能讓主程式碼更可靠.
我實現了一個簡單的方式,使用的是Junit的公開API, 測試過4.3和4.8.2,均可使用:
//得到所有帶@Test的方法,這裡用的是Nutz的資源掃描,反正你能得到全部Test類就行
List list = Scans.me().scanPackage("org.nutz");
List reqs = new ArrayList();
Map reqMap = new HashMap();
for (Class clazz : list) {
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if (method.getAnnotation(Test.class) != null) {
//將單個TestCase(即一個Test Method),封裝為Junit的Test Request
Request req = Request.method(clazz, method.getName());
reqs.add(req);
reqMap.put(req , method);//在最終列印測試結果時,方便查詢具體出錯的Method
}
}
}
// 因為reqs 是一個List,我們可以按需調整TestCase的順序
// 正序 //nothing change.
// 反序Collections.reverse(reqs)
// 亂序Collections.shuffle(reqs)
//把執行順序儲存下來,方便重現執行順序
try {
FileWriter fw = new FileWriter("./test_order.txt");
for (Request request : reqs) {
fw.write(reqMap.get(request).toString());
fw.write("\n");
}
fw.flush();
fw.close();
}
catch (IOException e) {}
//到這裡, List已經按我們預期的方式排好,可以執行測試了
final TestResult result = new TestResult();
RunNotifier notifier = new RunNotifier();
notifier.addListener(new RunListener() { //需要設定一個RunListener,以便收集測試結果
public void testFailure(Failure failure) throws Exception {
result.addError(asTest(failure.getDescription()), failure.getException());
}
public void testFinished(Description description) throws Exception {
result.endTest(asTest(description));
}
public void testStarted(Description description) throws Exception {
result.startTest(asTest(description));
}
public junit.framework.Test asTest(Description description) {
return new junit.framework.Test() {
public void run(TestResult result) {
throw Lang.noImplement();
}
public int countTestCases() {
return 1;
}
};
}
});
//來吧,執行之!!
for (Request request : reqs) {
request.getRunner().run(notifier);
}
//接下來,就是列印結果了.
System.out.printf("Run %d , Fail %d , Error %d \n", result.runCount(), result.failureCount(), result.errorCount());
if (result.failureCount() > 0) { //斷言失敗的TestCase
Enumeration enu = result.failures();
while (enu.hasMoreElements()) {
TestFailure testFailure = (TestFailure) enu.nextElement();
System.out.println("--Fail------------------------------------------------");
System.out.println(testFailure.trace());
testFailure.thrownException().printStackTrace(System.out);
}
}
if (result.errorCount() > 0) { //拋異常的TestCase
Enumeration enu = result.errors();
while (enu.hasMoreElements()) {
TestFailure testFailure = (TestFailure) enu.nextElement();
System.out.println("--ERROR------------------------------------------------");
System.out.println(testFailure.trace());
testFailure.thrownException().printStackTrace(System.out);
}
}
來, 考驗一下你的TestCase吧!! 讓它在亂序中多次執行. Nutz按這種思路,已經爆出幾個Bug(當然,我已經迅速fix了)
https://github.com/nutzam/nutz/blob/master/test/org/nutz/AdvancedTestAll.java
python中不好用,於是只好想一下其他的方法了。我想是不是可以把每個測試用例變成函式,然後再寫一個函式來順序呼叫它們呢?
這個方法雖然可以控制順序,可以也有一定的風險,如果出錯了,不會按測試用例給報錯,不能準確地統計出測試用例地正確率!如果全部通過則沒有問題,可是影響報告的結果,需要想辦法來美化一下報告。
修改後的程式碼如下:
#-*- coding: UTF-8 -*-
import time
import unittest
import sys
class DemoTest(unittest.TestCase):
def setUp(self):
….
Def a(self):
………
Def b(self):
………
Def c(self):
………
Def d(self):
………
Def test_demo(self):
a()
b()
c()
d()
Def tearDown(self):
………
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(DemoTest)
unittest.TextTestRunner(verbosity=2).run(suite)
相關文章
- pytest(4)-測試用例執行順序
- 測試平臺-unittest 指定順序執行用例
- 自定義xunit測試用例的執行順序
- sql中的or與and的執行順序問題SQL
- 關於defer執行順序問題
- SQL中rownum和order by的執行順序的問題SQL
- SQL語句中的AND和OR執行順序問題SQL
- connect by與where條件執行順序問題
- 演算法題-測試用例執行計劃演算法
- 一文搞懂Python Unittest測試方法執行順序Python
- C++輸出流cout的執行順序問題C++
- 【Oracle】where條件執行順序(上篇的問題延伸)Oracle
- GROUPBY 和開窗函式執行順序的問題函式
- Sql執行順序SQL
- Java中如何保證執行緒順序執行Java執行緒
- jest如何執行單組測試用例
- teprunner測試平臺測試計劃批量執行用例
- getView()執行次數問題(自己再次測試,順便做個記錄)View
- pytest多程式/多執行緒執行測試用例執行緒
- JavaScript執行順序分析JavaScript
- 任務執行順序
- for語句執行順序
- JavaScript的執行順序JavaScript
- laravel Event執行順序Laravel
- mySQL 執行語句執行順序MySql
- C#中Page執行順序:OnPreInit()、OnInit()……C#
- postman的批次執行:用於多條介面測試用例批次執行,輸出介面測試測試結果Postman
- mysql 中sql語句關鍵字的書寫順序與執行順序MySql
- Java for迴圈中語句執行的順序Java
- Qt中連線到同一signal的多個slots的執行順序問題QT
- js基礎進階–promise和setTimeout執行順序的問題JSPromise
- sql mysql 執行順序 (4)MySql
- SQL語句執行順序SQL
- js執行順序Event LoopJSOOP
- JavaScript for迴圈 執行順序JavaScript
- JavaScript 執行順序淺析JavaScript
- Angular單元測試如何只執行指定的測試用例,提高測試速度Angular
- Python執行緒專題10:queue、多執行緒按順序執行Python執行緒