iT邦幫忙

2023 iThome 鐵人賽

DAY 27
0

學習原因:

在測試中,同一個功能都會需要很多測試資料的組合來測試。若每一組 Test Data 都寫成一個測試用例,要寫的測試用例的數量就非常多了,且重覆性會很高,因此我們需要學習用 Data Driven Testing (DDT 數據驅動測試) 的方式去撰寫自動化測試。

此外,有些測試資料並非因 Test Case 而改變,而是因測試環境改變,我們把它會存成環境變數,以方便更動。此外,環境變數還有一個用途就是用來存機密的資料。這一篇就來說說 Test Data環境變數 的應用。

學習目標:

  • 使用 @pytest.mark.parametrize 實現 DDT
  • 認識什麼是環境變數,哪些資料適合寫成環境變數
  • 在 Jenkins 上設定環境變數和敏感性的資料

DDT (Data Driven Testing) 是一種測試方法,透過使用 不同的測試數據 來執行 相同的測試用例,以驗證系統在不同情況下的行為。在自動化測試中,DDT 通常涉及將測試數據從外部源(如 Excel 表格、CSV 文件、數據庫等)讀取,然後用於執行 Test Case。

應用 @pytest.mark.parametrize 實現 DDT

在 pytest 中可以用 @pytest.mark.parametrize 來實現 DDT,把數據參數化,通過對參數的賦值來驅動測試用例的執行。

# 以 num 存放 3 個測試數據,以參數的形式傳入 test case
# 這 Test Case 將會執行 3 次,而每次帶入不同的測試數據
@pytest.mark.parametrize("num", [1, 2, 3])
def test_number(num):
    print(f"Current Number : {num}")

# 以可以傳入多組參數,以 Tuple List 的形態傳入。
@pytest.mark.parametrize("num, result", [(1, 2), (2, 3), (3, 4)])
def test_add_1(num, result):
    assert num + 1 == result

Output:

tests/test_param.py::test_number[1] Current Number : 1
PASSED
tests/test_param.py::test_number[2] Current Number : 2
PASSED
tests/test_param.py::test_number[3] Current Number : 3
PASSED
tests/test_param.py::test_add_1[1-2] PASSED
tests/test_param.py::test_add_1[2-3] PASSED
tests/test_param.py::test_add_1[3-4] PASSED

導入 Excel 內容作為測試數據

為了更好管理測試的數據,我們可能會用到 Excel / Database 來存放大量測試數據。我們之前已經學過怎樣讀取 ExcelDatabase 的資料,可把這些內容寫成 function,回傳成 @pytest.mark.parametrize 傳參數的格式,即可為 Test Case 帶來不同的測試數據。以下是簡單的例子,會應用在 Day 07 所建的 Excel File。個人習慣 Test Data 都會存放在同一個資料夾以方便查閱,所以這裡建一個 /test_data 資料夾,再放入 Excel 檔案。

import pandas as pd
import pytest

def read_excel():
    score_df = pd.read_excel('test_data/score_table.xlsx')

    reading_score_list = []
    for index, row in score_df.iterrows():
        data = {
            "Reading": row["Reading"],
            "Writing": row["Writing"],
            "Listening": row["Listening"],
            "Speaking": row["Speaking"],
        }
    # 以 dict 型別存成 list
    reading_score_list.append(data)

    # 回傳作為 test case 的參數列,使用 dict list 可以一次傳入多個 test data
    return reading_score_list

# 在 @pytest.mark.parametrize 應用 function,則會以 function 的回傳值作為參數
@pytest.mark.parametrize("score_dict", read_excel())
def test_score(score_dict):
    print(f"Current Score Info: {score_dict}")

Output:

tests/test_excel.py::test_score[score_dict0] Current Score Info: {'Reading': 80, 'Writing': 80, 'Listening': 75, 'Speaking': 88}
PASSED
tests/test_excel.py::test_score[score_dict1] Current Score Info: {'Reading': 88, 'Writing': 95, 'Listening': 86, 'Speaking': 90}
PASSED
tests/test_excel.py::test_score[score_dict2] Current Score Info: {'Reading': 92, 'Writing': 98, 'Listening': 85, 'Speaking': 92}
PASSED
tests/test_excel.py::test_score[score_dict3] Current Score Info: {'Reading': 81, 'Writing': 82, 'Listening': 88, 'Speaking': 80}
PASSED
tests/test_excel.py::test_score[score_dict4] Current Score Info: {'Reading': 75, 'Writing': 80, 'Listening': 80, 'Speaking': 78}
PASSED

環境變數 Environment Variable

通常是為了提高程式的可配置性和安全性。我們會用 .env 來存放環境變數。

需注意的是,這個 .env 一般都不建議上傳到 Git 儲存庫,因為當中可能含有機密性的資料,可能導致資料外洩,從而危及系統和數據的安全。因此在專案會應用 .gitignore 防止 .env 檔上傳,另一方面會做一個 .env.sample 的範本,讓團隊成員在自己的本地環境中創建 .env 檔案。

以下是一些應該考慮設定為環境變數的資料類型:

  1. 敏感資訊:包括密碼、API 金鑰、驗證憑證等機密信息,這些資訊不應該明文存儲在程式碼中,而是設定為環境變數,以便更好地保護數據安全。
  2. 配置參數:例如數據庫連接信息、Domain 等,以便在不同環境中更輕鬆地進行切換和配置。
  3. 路徑設定:可能包括用於查找資源或驅動程式的路徑 (I.e. WebDriver 的路徑),可以使程式更靈活且易於移植。
  4. 測試數據:因應環境更改的測試數據,以便在不同測試情境下使用不同的測試數據。

需要在 Python 安裝 pytest-dotenv 套件,會自動讀取 .env 的資料成環境變數

pip install pytest-dotenv
# .env
DOMAIN="http://www.example.com"
# test_a.py
import os

def test_a():
	# 讀取環境變數 DOMAIN
	print(os.environ.get("DOMAIN"))

Output:

http://www.example.com

在 Jenkins 應用環境變數 .env 檔

Jenkins 執行的檔案是由 Git 儲存庫拉下來的,若我們把 .env 應用 .gitignore 以防止上傳,那 Jenkins 在執行時,則沒有環境變數可用。

這時候我們會把 .env 檔在 Jenkins 上存成 Secret FileSecret Text / Secret File 是儲存一些敏感的資訊的方式,將敏感資訊以加密的形式存儲在 Jenkins 中,並且可以在 Jenkins Job 中使用。可以降低數據外洩和機密泄漏的風險,同時提供了一個集中的地方來管理敏感資訊,有助於簡化 CI / CD 流程。

在 Jenkins Job 的 Configure 的 Build Environment,勾選 Use secret text(s) or file(s)

https://ithelp.ithome.com.tw/upload/images/20231001/20162038G6c3JRGpgN.png

可以 Secret file / Secret text 的方式儲存資料。

Secret Text 的話,需要逐個輸入,Variable 的名字要跟 .env 的 variable name 一致。

如果資料多的話,可以考慮使用 Secret file,但應用 secret file 需要修改一下程式碼。

https://ithelp.ithome.com.tw/upload/images/20231001/20162038AWzjERiPEi.png

# 根目錄下的 Conftest.py

# 在 Jenkins 中 Secret File 的 Variable 命為 ENV_FILE
# 當環境變數含有 ENV_FILE 代表正在 Jenkins 上運行,應用 load_dotenv () 讀取 Secret File
# 若沒有 ENV_FILE,則會讀取本地的 .env 檔
if 'ENV_FILE' in os.environ:
    env_file = os.environ['ENV_FILE']
    load_dotenv(env_file)

# 這寫法可讓你在本地端 / Jenkins 都能正常運作而不用修改程式碼。

Ref: 官方文件 https://docs.pytest.org/en/7.3.x/how-to/parametrize.html


上一篇
Day 26: PyTest 的 Conftest 與 Fixture
下一篇
Day 28: Parallel Testing
系列文
從 0 開始培育成為自動化測試工程師的學習指南30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言