Unittest 単体テスト フレームワークを使用するためのヒント

ここで使用する Unittest は Python の単体テスト フレームワークで、その公式 Web サイトは 25.3.unittest - Unit testing Framework - Python 2.7.18 ドキュメントで、包括的な情報を入手できます。

ユースケースを書くことが増えてくると、後のメンテナンスを容易にするためにユースケース作成の仕様や構成を考慮する必要があり、unittest はそのようなツールです。ここでは例を使用して、unittest スクリプトの使用がどのようなものかを示します。

1 # -*- coding: utf-8 -*-
 2 from selenium import webdriver
 3 from selenium.webdriver.common.by import By
 4 from selenium.webdriver.common.keys import Keys
 5 from selenium.webdriver.support.ui import Select
 6 from selenium.common.exceptions import NoSuchElementException
 7 from selenium.common.exceptions import NoAlertPresentException
 8 #导入unittest包
 9 import unittest, time, re
10 
11 #SearchTest类继承自unittest.TestCase,表明这是一个测试案例
12 class SearchTest(unittest.TestCase):
13     #setUp用于初始化工作
14     def setUp(self):
15         self.driver = webdriver.Firefox()
16         self.driver.implicitly_wait(30)
17         self.base_url = "https://www.baidu.com/"
18         self.verificationErrors = []
19         self.accept_next_alert = True
20 
21     #以test开头的是我们的测试脚本    
22     def test_search(self):
23         driver = self.driver
24         driver.get(self.base_url + "/")
25         driver.find_element_by_id("kw").click()
26         driver.find_element_by_id("kw").clear()
27         driver.find_element_by_id("kw").send_keys("selenium2")
28         driver.find_element_by_id("su").click()
29 
30     def is_element_present(self, how, what):
31         try: self.driver.find_element(by=how, value=what)
32         except NoSuchElementException as e: return False
33         return True
34 
35     def is_alert_present(self):
36         try: self.driver.switch_to_alert()
37         except NoAlertPresentException as e: return False
38         return True
39 
40     def close_alert_and_get_its_text(self):
41         try:
42             alert = self.driver.switch_to_alert()
43             alert_text = alert.text
44             if self.accept_next_alert:
45                 alert.accept()
46             else:
47                 alert.dismiss()
48             return alert_text
49         finally: self.accept_next_alert = True
50 
51     #在每个测试方法后执行,完成清理工作
52     def tearDown(self):
53         self.driver.quit()
54         self.assertEqual([], self.verificationErrors)
55 
56 #整个测试过程集中在unittest的main()模块中,其默认执行以test开头的方法
57 if __name__ == "__main__":
58     unittest.main()

これにより、unittest について直感的に理解できると思います。Unittest.main(): 単体テスト モジュールを直接実行できるテスト スクリプトに変換するために使用します。main() メソッドは、TestLoader クラスを使用して、モジュールに含まれる「test」で始まるすべてのテスト メソッドを検索します。自動的に実装されます。実行メソッドのデフォルトの順序は次のとおりです: ASCII コードの順序に従ってテスト ケースをロードします。数字と文字の順序は 0 ~ 9、AZ、az です。したがって、A で始まるテスト ケース メソッドが最初に実行され、a で始まるテスト ケース メソッドが後で実行されます。

Unittest の
TestCase の概念
は、Testcase インスタンスです。テスト ケースは、setUp の初期化、run の実行、テスト後のtearDown の復元を含む、完全なテスト プロセスです。unittest.TestCase クラス。すべてのテスト ケース クラスによって継承される基本クラス。このクラスは、比較をチェックするための多くのアサート メソッドを提供します。そのうちのいくつかは次のとおりです。

ほとんどのメソッドは名前を見れば理解できるため、使用の敷居は非常に低いです。

TestSuite では、
関数をテストするために複数のテスト ケースが必要になることが多く、複数のテスト ケースを同時に実行することができます。これが TestSuite の概念です。addTest() メソッドは、テスト ケースをテスト スイートに追加するためによく使用されます。

TextTestRunner は
テスト ケースの実行に使用され、run(test) は TestSuite/TestCase の実行に使用されます。テストの結果は TextTestResult インスタンスに保存されます。

TestFixture テスト
の準備前に実行する作業とテストの実行後に実行する作業 (setUp() と TearDown() を含む)。これは、TestCase の setUp と TearDown をオーバーライドすることで実現されます。

これらの主な概念を理解した上で、上記のスクリプトの Unittest.main() の最後の行を次のコードに変更できます。

1 #テスト スイートの構築
2 suite =unittest.TestSuite()
3 suite.addTest(SearchTest("test_search"))
4 #テストの実行
5 Runner = Unittest.TextTestRunner()
6 Runner.run(suite)
は実行後に検出され、実行前に使用されましたUnittest.main() の結果は同じです。

ユースケースの構成
ここでは、スクリプト内に test_case1、test_case2... などの複数の TestCase があると仮定します。その場合、それらの実行順序をどのように制御すればよいでしょうか。

テストケース計画を実行する 1.
直接使用する

Unittest.main()
が実行され、test で始まるすべてのテスト ケース メソッドが検索され、複数のテスト ケースが ASCII 順に実行されます。

テスト ケースを実行するためのオプション 2:
最初にテスト スイートをインスタンス化し、ユース ケースをロードしてから、TextTestRunner を使用してユース ケースを実行します。

1 suite=unittest.TestSuite()
2 suite.addTest(Test('test_case2'))
3 suite.addTest(Test('test_case1'))
4 Runner=unittest.TextTestRunner()
5 Runner.run(suite)
実行順序はユースケースの読み込み順序で、例えばここでは2が先に実行され、1が後に実行されます。

実行テスト ケース シナリオ 3
シナリオ 2 では、数百または数千のユース ケースがある場合、それらを 1 つずつ追加するのは非現実的であるため、defaultTestLoader を使用してロードできます。

1 test_dir = './'
2 Discover = Unittest.defaultTestLoader.discover(test_dir, pattern='*test.py')
3 Runner = Unittest.TextTestRunner()
4 Runner.run(discover)
ここでは ./ を使用して現在のdirectory に *test.py ファイルが指定され、その中のユースケースがプラン 1 と同じ順序で実行されます。

ここで指定したディレクトリの下に、パターンに一致する複数の .py ファイルがある場合はどうなるでしょうか? Discover メソッドを呼び出すには、まず test_dir を通じて検索ディレクトリを定義します。ファイル名が定義されたパターンに一致する場合は、for ループを使用してフィルタリングされたすべてのユース ケースを検索し、ループ内のスイートに追加する必要があります。コードは次のとおりです。

1 は、discover の test_suite の場合:
2 は、test_suite の test_case の場合:
3 test_unit.addTests(test_case)
上記のユースケースの整理方法から、実際のテスト スクリプトの開発では、ディレクトリに xx.py ファイルを作成できることがわかります。テスト ケースが安定して実行されたら、テスト スイートへの追加を容易にするために、test_xx.py に変更できます。ファイル名の一致ルールは pattern パラメータで定義できることに注意してください。

マルチレベルのディレクトリ構造でユースケースを実行したい場合はどうすればよいでしょうか? Discover によって読み取られて実行されるようにするには、_ init _.py ファイルをディレクトリに追加する必要があります。


以下は、unittest によって構成されたユース ケース構造の簡単な紹介です。まず、D:\Test_Project ディレクトリを作成し、その下に test_case と test_report を配置して、それぞれユース ケースとレポートを保存します。

テスト ケースを作成します。test_case
の下にテスト ケースを作成します。以下は、Baidu でキーワードを検索し、[設定] をクリックする簡単なデモンストレーションです。

 1 文件名为:test_baidu.py
 2 
 3 # -*- coding: utf-8 -*-
 4 from selenium import webdriver
 5 import unittest, time, re
 6 
 7 class MyTest(unittest.TestCase):
 8 
 9     def setUp(self):
10         self.driver = webdriver.Firefox()
11         self.driver.implicitly_wait(30)
12         self.base_url = "https://www.baidu.com"
13         self.accept_next_alert = True
14 
15     def test_02baidu_search(self):
16         u''' 测试百度搜索'''
17         driver = self.driver
18         driver.get(self.base_url + "/")
19         driver.find_element_by_id("kw").click()
20         driver.find_element_by_id("kw").clear()
21         driver.find_element_by_id("kw").send_keys("selenium-test")
22         driver.find_element_by_id("su").click()
23         print("test_baidu__test_02baidu_search")
24 
25     def test_01baidu_setting(self):
26         u''' 测试百度首页设置 '''
27         driver = self.driver
28         driver.get(self.base_url + "/")
29         driver.find_element_by_css_selector("div#u1 a.pf").click()
30         driver.find_element_by_class_name("setpref").click()
31         driver.find_element_by_css_selector("div#gxszButton>a.prefpanelgo").click()
32         driver.switch_to_alert().accept()
33         print("test_baidu__test_01baidu_setting")
34 
35     def tearDown(self):
36         self.driver.close()
37 
38 #从all_test中调用时,可以不要这个
39 if __name__ == "__main__":
40     unittest.main()

テスト ケースを整理した効果を示すために、このファイルを再度コピーし、ファイル名とメソッド名を変更します。

 1 文件名为:test_baidu2.py
 2 
 3 # -*- coding: utf-8 -*-
 4 from selenium import webdriver
 5 import unittest, time, re
 6 
 7 class MyTest(unittest.TestCase):
 8     u''' 测试baidu的第二个用例'''
 9     def setUp(self):
10         self.driver = webdriver.Firefox()
11         self.driver.implicitly_wait(30)
12         self.base_url = "https://www.baidu.com"
13         self.accept_next_alert = True
14 
15     def test_02baidu_search(self):
16         u''' 测试baidu的第二个用例的test_02baidu_search'''
17         driver = self.driver
18         driver.get(self.base_url + "/")
19         driver.find_element_by_id("kw").click()
20         driver.find_element_by_id("kw").clear()
21         driver.find_element_by_id("kw").send_keys("selenium-test")
22         driver.find_element_by_id("su").click()
23         print("test_baidu2__test_02baidu_search")
24 
25 
26     def test_01baidu_setting(self):
27         u''' 测试baidu的第二个用例的test_01baidu_setting'''
28         driver = self.driver
29         driver.get(self.base_url + "/")
30         driver.find_element_by_css_selector("div#u1 a.pf").click()
31         driver.find_element_by_class_name("setpref").click()                        driver.find_element_by_css_selector("div#gxszButton>a.prefpanelgo").click()
32         driver.switch_to_alert().accept()
33         print("test_baidu2__test_01baidu_setting")
34 
35     def tearDown(self):
36         self.driver.close()
37 
38 if __name__ == "__main__":
39     unittest.main()

レポートのスタイルを美しくし、結果を電子メールで送信します。
上では例として 2 つのテスト ケースを作成しましたが、さらに追加することもできます。次に、オープン ソース モジュール HTMLTestRunner を使用してテスト レポートを美しくします。ダウンロードと使用方法については、HTMLTestRunner · PyPI を参照してください。次に、操作の完了後にテストメールが自動的に送信されるようにコードを記述して、簡単に確認できるようにします。次のコードを参照してください。

 1 #coding=utf-8
 2 import unittest
 3 import smtplib
 4 from email.mime.text import MIMEText
 5 from email.header import Header
 6 import time
 7 import HTMLTestRunner
 8 from email.mime.application import MIMEApplication
 9 
10 #---发送邮件---
11 def send_email(report_file):
12     sender = "[email protected]"
13     receiver = "[email protected]"
14     smtpserver = "smtp.qq.com"
15     #发送邮箱的账号密码,此处使用的是qq邮箱和第三方登录的授权码
16     username = "[email protected]"
17     password = "gfomcomojtuudijc"
18 
19     #定义邮件正文
20     file = open(report_file,"rb")
21     mail_body = file.read()
22     file.close()
23 
24     msg = MIMEText(mail_body, _subtype="html", _charset="utf-8")
25     msg["Subject"] = u"自动化测试报告"
26 
27     smtp = smtplib.SMTP_SSL("smtp.qq.com")
28     smtp.login(username, password)
29     smtp.sendmail(sender, receiver, msg.as_string())
30     smtp.quit()
31     print("Email has send out !")
32 
33 #---将用例添加到测试套件---
34 def creatsuite():
35     testunit=unittest.TestSuite()
36     test_dir = "D:\\Test_Project\\test_case"
37     discover = unittest.defaultTestLoader.discover(test_dir, pattern="test*.py",
38                                                  top_level_dir = None)
39     for test_suite in discover:
40         for test_case in test_suite:
41             testunit.addTest(test_case)
42             print (testunit)
43     return testunit
44 
45 if __name__ == "__main__":
46     current_time = time.strftime("%Y-%m-%d-%H-%M")
47     report_dir = "D:\\Test_Project\\test_report\\"
48     report_file = report_dir + current_time + "-Test_Result.html"
49     report_stream = open(report_file, "wb")
50     # runner = unittest.TextTestRunner()
51     # 注意HTMLTestRunner只支持python2
52     runner = HTMLTestRunner.HTMLTestRunner(stream=report_stream,title=u"自动化测试报告",  description=u"用例执行情况如下:")
53     runner.run(creatsuite())
54     report_stream.close()
55     send_email(report_file)

上記のコードでは、HTMLTestRunner モジュールを使用して美しいレポートを出力するために、runner = Unittest.TextTestRunner() の代わりに、runner = HTMLTestRunner.HTMLTestRunner() メソッドを使用します。次に、電子メールを送信するメソッドを呼び出します。このファイルを実行すると、次の出力レポートを取得できます。

これを利用すると、ユースケースの実行状況が一目瞭然で、失敗したユースケースの原因を確認してデバッグするのにも便利であると同時に、通知メールも届きます。入力した受信箱。この出力レポートをテキストまたは添付ファイルに追加して、見やすくすることができます

最後に、私の記事を注意深く読んでくださった皆さんに感謝します。互恵性は常に必要です。それほど価値のあるものではありませんが、使用できる場合は、直接受け取ることができます。 

書類の入手方法:

このドキュメントは、[ソフトウェア テスト] に参加したい友人にとって、最も包括的で完全な準備倉庫となるはずです。この倉庫は、私が最も困難な旅を乗り越えるのにも同行してくれました。また、あなたのお役に立てれば幸いです。

上記はすべて共有できます。下の小さなカードをクリックして無料で入手してください

おすすめ

転載: blog.csdn.net/2301_77645573/article/details/132812586