1. 程式人生 > 其它 >五、自動執行測試

五、自動執行測試

json

json檔案是一個特殊格式的文字檔案

  • json是一種語法, 用來表達一些資料的
  • json檔案的內容就是用json表達的一些資料
  • json的語法格式類似於python字典, 由大括號包裹, 有鍵,每個鍵對應一個值
{
    "name":"tom",
    "age":30
}

json讀json檔案

import json
open讀的方式開啟json檔案
dict1 = json.load(開啟檔案物件) # 把json檔案的內容讀取到python的字典dict1中
close關閉已經開啟的json檔案
# 讀取a.json檔案, 顯示鍵"age"對應的值
import json
file = open("a.json", "r", encoding="utf-8")
dict1 = json.load(file) # 把json檔案的內容, 轉化成一個python的字典
file.close()
print(dict1["age"])

a.json

{
    "name":"tom",
    "age":30
}

寫json檔案

import json
open用寫的方式開啟檔案
json.dump(字典, open開啟的檔案物件, ensure_ascii=False) ensure_ascii=False中文不轉義
關閉檔案
import json
file = open("a.json", "w", encoding="utf-8")
dict1 = {"name":"劉備", "height":1.75}
json.dump(dict1, file, ensure_ascii=False) # ensure_ascii=False 中文不轉義
file.close()

pytest

pytest自動執行測試用例

  • 測試用例所在的模組(py)命名一定要採用識別符號的命名規則
  • 一個測試用例就是一個方法
  • 方法名習慣test開頭
  • 方法所在的類習慣Test開頭, 並採用大駝峰命名法
import pytest
if __name__ == "__main__":
    pytest.main(["-s", "測試用例所在的py檔名", "其他的測試用例所在的檔案.py"]) 
# "-s"作用是, 如果沒有-s測試用例中的print將不會輸出任何內容
# m1.py
# 被測試的函式
def my_sum(a, b):
    return a + b
# m2.py 存放測試用例
# 測試m1.py中的my_sum函式是否正確
from m1 import my_sum
'''
測試用例
測試資料, 一個實參為4, 一個實參為2, 預期結果為6
'''
# 一個測試用例就是一個方法, 所以一定先要定義一個類
class TestFunc:  # 存放測試用例的類, 業內習慣Test開頭, 並且採用大駝峰命名法
    # 類當中的方法就是測試用例
    def test_01(self): # 這個方法就是測試用例, 名字習慣以小寫test開頭
        result = my_sum(4, 2)
        if result == 6:
            print("測試通過")
        else:
            print("測試失敗")

    def test_02(self):
        result = my_sum(1, 2)
        if result == 3:
            print("測試通過")
        else:
            print("測試失敗")
# m3.py 存放測試用例

class TestM:
    def test_01(self):
        print("我是TestM中的測試用例test_01")
  • pytest中執行測試用例的程式碼
import pytest

if __name__ == "__main__":
    pytest.main(["-s", "m2.py", "m3.py"])  #"-s"的意思是執行測試用例的時候, 顯示print的輸出, "m2.py"測試用例所在的檔名

斷言

  • 用程式碼判斷測試用例執行是否通過
assert 條件 # 條件成立, 代表斷言通過, 否則代表斷言不通過
# m2.py 存放測試用例
# 測試m1.py中的my_sum函式是否正確
from m1 import my_sum
'''
測試用例
測試資料, 一個實參為4, 一個實參為2, 預期結果為6
'''
# 一個測試用例就是一個方法, 所以一定先要定義一個類
class TestFunc:  # 存放測試用例的類, 業內習慣Test開頭, 並且採用大駝峰命名法
    # 類當中的方法就是測試用例
    def test_01(self): # 這個方法就是測試用例, 名字習慣以小寫test開頭
        result = my_sum(4, 2)
        assert result == 6  # result是實際執行結果, 6是預期結果, 實際結果與預期結果相同, 斷言通過

    def test_02(self):
        result = my_sum(1, 2)
        assert result == 3

if __name__ == "__main__":
    TestFunc().test_01() # 把TestFunc這個類例項化後,直接呼叫test_01方法
'''
    t = TestFunc()
    t.test_01()
'''
# m3.py 存放測試用例

class TestM:
    def test_01(self):
        assert True   # 這個測試用例永遠不會失敗

setup和teardown

  • 測試用例所在的類可以定義兩個方法, 一個是setup, 一個是teardown
  • 如果一個類中有多個測試用例, 每個測試用例執行前會自動呼叫setup方法, 每個測試用例執行完成後會自動呼叫teardown方法
# m2.py 存放測試用例
# 測試m1.py中的my_sum函式是否正確
from m1 import my_sum
'''
測試用例
測試資料, 一個實參為4, 一個實參為2, 預期結果為6
'''
# 一個測試用例就是一個方法, 所以一定先要定義一個類
class TestFunc:  # 存放測試用例的類, 業內習慣Test開頭, 並且採用大駝峰命名法
    # 類當中的方法就是測試用例
    def test_01(self): # 這個方法就是測試用例, 名字習慣以小寫test開頭
        result = my_sum(4, 2)
        assert result == 6  # result是實際執行結果, 6是預期結果, 實際結果與預期結果相同, 斷言通過

    def test_02(self):
        result = my_sum(1, 2)
        assert result == 3

    def setup(self):
        print("setup方法給呼叫了")

    def teardown(self):
        print("teardown方法給調動了")

if __name__ == "__main__":
    TestFunc().test_01() # 把TestFunc這個類例項化後,直接呼叫test_01方法
'''
    t = TestFunc()
    t.test_01()
'''

setup_class和teardown_class

  • 一個類中不管有多少測試用例, 所有測試用例執行前, 自動呼叫一次setup_class, 所以測試用例執行完成後自動呼叫一次teardown_class
# m2.py 存放測試用例
# 測試m1.py中的my_sum函式是否正確
from m1 import my_sum
'''
測試用例
測試資料, 一個實參為4, 一個實參為2, 預期結果為6
'''
# 一個測試用例就是一個方法, 所以一定先要定義一個類
class TestFunc:  # 存放測試用例的類, 業內習慣Test開頭, 並且採用大駝峰命名法
    # 類當中的方法就是測試用例
    def test_01(self): # 這個方法就是測試用例, 名字習慣以小寫test開頭
        result = my_sum(4, 2)
        assert result == 6  # result是實際執行結果, 6是預期結果, 實際結果與預期結果相同, 斷言通過

    def test_02(self):
        result = my_sum(1, 2)
        assert result == 3

    def setup(self):
        print("setup方法給呼叫了")

    def teardown(self):
        print("teardown方法給調動了")

    def setup_class(self):
        print("setup_class方法給呼叫了")

    def teardown_class(self):
        print("teardown_class方法給調動了")

if __name__ == "__main__":
    TestFunc().test_01() # 把TestFunc這個類例項化後,直接呼叫test_01方法
'''
    t = TestFunc()
    t.test_01()
'''

引數化

  • 多個測試用例, 程式碼完全相同, 只有測試資料與預期結果不同, 使用引數化後可以去掉冗餘程式碼
import pytest

# 在要使用引數化的方法前
@pytest.mark.parametrize("形參的說明", [(形參對應的實參), (形參對應的實參), (....)])
def 測試用例(self, 和形參的說明裡一樣的具體形參):
    pass
[裡有幾個元組, 被引數化的方法就會自動執行幾次]
# m4.py 存放測試用例
# 測試m1.py中的my_sum函式是否正確
import pytest
from m1 import my_sum
'''
測試用例1
測試資料, 一個實參為4, 一個實參為2, 預期結果為6
測試用例2
測試資料, 一個實參為1, 一個實參為2, 預期結果為3
測試用例3
測試資料, 一個實參為10, 一個實參為1, 預期結果為11
'''
class TestFunc:
    @pytest.mark.parametrize("a, b, expect", [(4, 2, 6), (1, 2, 3), (10, 1, 11)])
    def test_01(self, a, b, expect): # a和b代表調動my_sum提供的實參, expect代表預期結果
        result = my_sum(a, b)
        assert result == expect

生成html版本測試報告

import pytest

if __name__ == "__main__":
    pytest.main(["-s", "--html=a.html", "m4.py"])  #"-s"的意思是執行測試用例的時候, 顯示print的輸出, "m2.py"測試用例所在的檔名

pytest.ini配置檔案

  • pytest.ini配置檔案一定要在專案目錄裡, 不能在任何一個包裡
[pytest]
addopts = -s --html=a.html
testpaths = ./
python_files = m*.py
python_classes = Test*
python_functions = test*
  • 第一行必須為[pytest]
  • 第二行, -s代表執行測試用例的時候, 可以顯示print的輸出結果, --html=a.html 生成測試報告的檔名
  • 第三行: 在哪個包裡查詢測試用例所在的py檔案
  • 第四行: 測試用例所在的py檔名, 支援萬用字元 m*.py查詢所有以m開頭, .py結尾的檔案
  • 第五行: 測試用例所在的類名必須以Test開頭
  • 第六行: 測試用例的方法名必須以test開頭
import pytest

if __name__ == "__main__":
    pytest.main() # 啟用pytest.ini配置檔案, 來執行測試用例

總結