1. 程式人生 > 其它 >pytest + yaml 框架 -12.支援執行sql 和 斷言sql

pytest + yaml 框架 -12.支援執行sql 和 斷言sql

前言

當我們在測試環境寫好自動化的程式碼,領導說你把程式碼部署到聯調環境再測一測,這時候去改用例裡面的配置是很痛苦的。
所以我們在設計自動化用例的時候,就先要想到多環境的配置與切換。

多環境配置

如果需用到多套環境 test/uat 等,那麼應該在用例的根目錄(pytest.ini 同級檔案)建立一個config.py 檔案
pip 安裝外掛

pip install pytest-yaml-yoyo

多套環境切換功能在 v1.0.10 版本上實現


class Config:
    """多套環境的公共配置"""
    version = "v1.0"


class TestConfig(Config):
    """測試環境"""
    BASE_URL = 'http://192.168.1.1:8000'
    MYSQL_HOST = "192.168.1.1"
    MYSQL_USER = "root"
    MYSQL_PASSWORD = "123456"
    MYSQL_PORT = 3306
    MYSQL_DATABASE = "xxx"   # 連線資料的庫名


class UatConfig(Config):
    """聯調環境"""
    BASE_URL = 'http://192.168.1.3:8080'
    MYSQL_HOST = "http://192.168.1.3"
    MYSQL_USER = "root"
    MYSQL_PASSWORD = "654321"
    MYSQL_PORT = 3306
    MYSQL_DATABASE = "xxx"  # 連線資料的庫名


# 環境關係對映,方便切換多環境配置
env = {
    "test": TestConfig,
    "uat": UatConfig
}

按以上的配置格式,配置不同的環境,最後做一個環境名稱和配置的對映關係,必須是 env 命名,格式如下

env = {
    "test": TestConfig,
    "uat": UatConfig
}

那麼在執行用例的時候,可以選擇執行test 環境還是uat 環境,有 2 種方式可以配置待執行的環境

方法一: 在pytest.ini 中配置

[pytest]


env = test

方法二: 執行 pytest 命令的時候設定

pytest --env test

如果2個地方都有設定,那麼優先順序是:命令列引數 --env test 大於 pytest.ini 中配置env = test

.

測試環境的BASE_URL

在上一篇中講到 pytest + yaml 框架 -11.全域性 base_url 配置

環境地址優先順序使用如下:
1.全域性配置命令列引數--base-url優先順序大於 pytest.ini 檔案中的base_url 配置。
2.yaml 檔案 config 中的base_url 優先順序大於全域性配置
3.request 請求的url 如果是絕對地址,那麼base_url 無效
總的來說 : url 絕對地址 > config 中的base_url > 命令列引數--base-url > pytest.ini 檔案中的base_url

這裡我們新增了一個在config.py 中也可以配置全域性的base_url (config.py 中的配置用大寫命名 BASE_URL)

如果在 config.py 中配置全域性的 BASE_URL ,那麼也會生效。優先順序會低於命令列和 pytest.ini 的配置

總的來說:url 絕對地址 > config 中的base_url > 命令列引數--base-url > pytest.ini 檔案中的 base_url > config.py 的 BASE_URL

mysql 資料庫配置

如果用例中需要執行mysql 資料庫,或者在斷言的時候需要查詢mysql 資料庫。先在config.py 中完成配置

class TestConfig(Config):
    """測試環境"""
    BASE_URL = 'http://192.168.1.1:8000'
    MYSQL_HOST = "192.168.1.1"
    MYSQL_USER = "root"
    MYSQL_PASSWORD = "123456"
    MYSQL_PORT = 3306
    MYSQL_DATABASE = "xxx"   # 連線資料的庫名

當完成了MYSQL 相關的五個配置,那麼有個內建的函式可以使用

  • query_sql(sql) 查詢sql, 查詢無結果返回None, 查詢只有一個結果返回dict, 查詢多個結果返回list of dict
  • execute_sql(sql) 執行sql, 操作新增,修改,刪除的sql

斷言執行sql

使用示例

config:
  base_url: http://124.70.221.221:8201
  variables:
    username: test
    sql: select * from auth_user where username like 'test';

登入:
    name: step login
    request:
        url: /api/v1/login
        method: POST
        json:
            username: ${username}
            password: "123456"
    extract:
        token: $.token
    validate:
        - eq: [status_code, 200]
        - eq: [ok, true]
        - eq: [$.username, '${query_sql(sql).username}']

以上示例是斷言的時候,執行sql,獲取資料庫的值

- eq: [$.username, '${query_sql(sql).username}']

可以開啟日誌

[pytest]

log_cli = true
log_cli_level = debug
env = test

檢視執行日誌

body:
     {"code": 0, "msg": "login success!", "username": "test", "token": "6112772900193da079e9fcc857613f6125
3648fd"}

2022-12-13 10:34:54 [INFO]: extract 提取變數-> {'token': '6112772900193da079e9fcc857613f61253648fd'}
2022-12-13 10:34:54 [DEBUG]: query sql: select * from auth_user where username like 'test';!
2022-12-13 10:34:54 [INFO]: query result: {'id': 2, 'password': 'pbkdf2_sha256$100000$rSQNBkIc2xOm$VGXiUZk
dsIueT/AsoPwlFSEL1vGODsK7eIjK0nawH/M=', 'last_login': None, 'is_superuser': 0, 'username': 'test', 'first_
name': '', 'last_name': '', 'email': '[email protected]', 'is_staff': 0, 'is_active': 1, 'date_joined': dateti
me.datetime(2022, 11, 11, 21, 22, 59, 971425)}
2022-12-13 10:34:54 [INFO]: validate 校驗內容-> [{'eq': ['status_code', 200]}, {'eq': ['ok', True]}, {'eq'
: ['$.username', 'test']}]
2022-12-13 10:34:54 [INFO]: validate 校驗結果-> eq: [200, 200]
2022-12-13 10:34:54 [INFO]: validate 校驗結果-> eq: [True, True]
2022-12-13 10:34:54 [INFO]: validate 校驗結果-> eq: [test, test]

從返回的body 裡面提取username 使用表示式$.username, 得到實際結果"test"
'${query_sql(sql).username}' 表示式會先呼叫query_sql(sql) 函式,引用前面設定的變數sql, 得到結果

{'id': 2, 'password': 'pbkdf2_sha256$100000$rSQNBkIc2xOm$VGXiUZk
dsIueT/AsoPwlFSEL1vGODsK7eIjK0nawH/M=', 'last_login': None, 'is_superuser': 0, 'username': 'test', 'first_
name': '', 'last_name': '', 'email': '[email protected]', 'is_staff': 0, 'is_active': 1, 'date_joined': dateti
me.datetime(2022, 11, 11, 21, 22, 59, 971425)}

得到的結果是一個字典,字典物件可以繼續取值,於是'${query_sql(sql).username}' 就可以得到期望結果 "test"

用例的引數也可以查詢sql

如果用例的引數,需要從sql中取值,我們也可以先定義變數,在用例中引用query_sql(sql) 函式

config:
  variables:
    sql: select * from auth_user where username like 'test';

登入:
    name: step login
    request:
        url: /api/v1/login
        method: POST
        json:
            username: ${query_sql(sql).username}
            password: "123456"
    extract:
        token: $.token
        x: ${query_sql(sql).username}
    validate:
        - eq: [status_code, 200]
        - eq: [ok, true]
        - eq: [$.username, test]

extract 中也可以支援執行sql,得到提取結果

  extract:
        token: $.token
        x: ${query_sql(sql).username}

用例前置和後置執行sql

如果需要在用例的前置和後置中執行sql, 可以用到hook 機制,在請求前和請求後執行函式
參考前面這篇pytest + yaml 框架 -6.hooks 鉤子功能實現