tep用戶手冊幫你從unittest過渡到pytest

unittest和pytest是Python的2個強大的測試框架,經常用來做UI自動化或介面自動化。unittest是PyCharm的默認集成工具,也是我們大多數人入門自動化的首選框架。pytest提供了更豐富的功能,相對的上手難度也要高一點。如果學了pytest後,想快速用pytest寫項目,用於工作實踐,那麼可以試試我寫的這款測試工具:tep,try easy pytest。

tep簡介

在Google中輸入python tep

tep是一款測試工具,不是測試框架,它做的事情只是幫助你更輕鬆的使用pytest寫項目程式碼,主要功能如下:

  • 項目腳手架
  • pytest用例組織
  • 輸出HTML測試報告
  • 基於fixture管理環境變數
  • 基於fixture共享公共函數
  • 訪問MySQL資料庫
  • 集成常用第三方包
  • 登錄介面示例程式碼

工具安裝

安裝

tep已經上傳到了PyPI(Python Package Index):

可以使用pip命令安裝:

pip install tep

外網速度慢,pandas可能安裝失敗,推薦用中國鏡像:

pip --default-timeout=6000 install -i //pypi.tuna.tsinghua.edu.cn/simple tep

由於集成了第三方包,安裝可能會花幾分鐘,請耐心等待。

Python版本 3.6+

檢查

安裝完成後,檢查是否安裝成功:

tep -V
0.5.3

或者:

tep --version
0.5.3

升級

使用-U參數:

pip install -U tep

或者指定版本:

pip install tep==0.5.3

快速創建項目

tep提供了腳手架,預置了項目結構和程式碼,打開cmd,使用startproject命令快速創建項目:

cd some_directory
tep startproject project_name

startproject

創建後的項目結果如下:

當前版本主要用來做介面自動化,建議把不同業務系統建成多個項目。

1個文件2處修改完成登錄請求

tep已經預置了登錄相關程式碼,只需要打開fixtures\fixture_admin.py,修改2個地方的程式碼,就可以完成登錄請求。

修改環境變數

編輯fixtures/fixture_admin.py

@pytest.fixture(scope="session")
def env_vars(config):
    class Clazz:
        def __init__(self):
            env = config["env"]
            self.mapping = {
                "qa": {
                    "domain": "//qa.com",
                    "mysql_engine": mysql_engine("127.0.0.1",  # host
                                                 "2306",  # port
                                                 "root",  # username
                                                 "123456",  # password
                                                 "test")  # db_name
                },
                "release": {
                    "domain": "//release.com",
                    "mysql_engine": mysql_engine("127.0.0.1",
                                                 "2306",
                                                 "root",
                                                 "123456",
                                                 "release")
                }
                # Add your env and variables
            }
            self.domain = self.mapping[env]["domain"]
            self.mysql_engine = self.mapping[env]["mysql_engine"]
            # Add properties

        def add(self, env, key, value):
            self.mapping[config["env"]][key] = value

    return Clazz()

mapping是個字典,預置了2個環境:qarelease,每個環境預置了2個變數:domainmysql_engine

domain

url = domain +uri,例如//qa.com/api/users/login/的domain是“//qa.com,uri是/api/users/login/`。

首先把qa環境的domain值改為你的測試域名。

修改登錄程式碼

繼續編輯fixtures/fixture_admin.py

def _jwt_headers(token):
    return {"Content-Type": "application/json", "authorization": f"Bearer {token}"}


@pytest.fixture(scope="session")
def login():
    # Code your login
    logger.info("Administrator login")
    response = request(
        "post",
        url=url("/api/users/login/"),
        headers={"Content-Type": "application/json"},
        json={
            "username": "admin",
            "password": "123456",
        }
    )
    assert response.status_code < 400
    response_token = jmespath.search("token", response.json())

    class Clazz:
        token = response_token
        jwt_headers = _jwt_headers(response_token)

    return Clazz

# Code your login處開始修改程式碼,替換API路徑/api/users/login/和請求參數json。如果你的登錄介面不會返回token,那麼修改jmespath.search("token", response.json())為實際響應取值。

tep預置登錄返回了2個值:tokenjwt_headers

測試登錄

打開tests/login_test.py

from loguru import logger


def test_login(login):
    logger.info(login.token)

執行後就會調用登錄介面發起請求。

遇到問題無法解決請留言或加群。

編寫測試用例

用例組織

測試用例全部放在tests目錄下:

每個.py模組以test_前綴或_test後綴命名,每個test函數以test前綴命名。只要遵循這個規則,目錄層次不影響。示例:

建議每個.py模組只包含1個test函數,也就是1條測試用例。

介面請求設計

每條測試用例可以包含單個或多個介面請求。tep預置了1個POST請求示例程式碼,打開tests/post_test.py

import jmespath
from loguru import logger

from tep.client import request


def test_post(faker_ch, url, login):
    # description
    logger.info("test post")
    # data
    fake = faker_ch
    # request
    response = request(
        "post",
        url=url("/api/users"),
        headers=login.jwt_headers,
        json={
            "name": fake.name()
        }
    )
    # assert
    assert response.status_code < 400
    # extract
    user_id = jmespath.search("id", response.json())

每個請求由5部分組成,從上往下分別是描述、數據、請求、斷言和提取。

借鑒了JMeter元件和參數化關聯的設計思想。

描述

描述這個請求是幹嘛的。

數據

初始化局部變數,例如使用faker庫造測試數據。

請求

如果需要列印請求日誌,可以from tep.client import requesttep.client.requestrequests.request除了記錄日誌外,沒有做任何修改。

如果請求報錯了,那麼很可能是程式碼寫錯了。

也可以直接使用原生requestfrom requests import request

不同請求方法的程式碼如下:

request("get", url="", headers={}, json={})
request("post", url="", headers={}, params={})
request("put", url="", headers={}, json={})
request("delete", url="", headers={})

# 上傳excel
request("post",
        url="",
        headers={},
        files={
            "file": (
                file_name,
                open(file_path, "rb"),
                "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
            )
        },
        verify=False
    )

更多用法參考requests.request

斷言

斷言使用Python標準斷言assert 表達式,表達式跟if語句表達式一模一樣。

提取

推薦使用jmespath提取JSON數據,也可以使用Python[]中括弧提取。

HTML測試報告

批量執行用例

單個測試用例,在PyCharm中執行就可以了。多個測試用例批量執行,需要打開左下角的Terminal,輸入命令來執行:

# 先進入tests目錄
cd tests
# 批量執行
pytest

只收集不執行

如果只想統計用例條數,不執行程式碼,那麼可以使用以下命令:

pytest --co

HTML測試報告

tep提供了--tep-reports參數來生成allure測試報告:

pytest  --tep-reports

報告文件存放在根目錄的reports/中:

右鍵index.html選擇:

就會打開瀏覽器顯示測試報告了:

image-20201222172647121

默認allure報告右上角的TREND是無法顯示數據的,--tep-reports修復了這個問題,根據history數據生成TREND走勢圖。

自定義環境變數

靜態添加

編輯fixtures/fixture_admin.py,在mapping字典中# Add your env and variables處添加環境變數,在# Add properties處添加屬性,參考domainmysql_engine。示例:

動態添加

使用add()方法動態添加環境變數:

env_vars.add("my_var", 789)

使用環境變數

env_vars返回了類對象實例,通過.運算符來使用環境變數:

env_vars.domain
env_vars.mysql_engine
env_vars.my_var

不需要import,而是給test函數添加參數,如def test(env_vars):

切換環境

conf.yaml文件中配置:

env: qa

默認為qa環境。

團隊共享公共函數

通過fixture技術,我們可以把重複程式碼提取出來,在團隊間進行復用。tep重度使用了這個技術,在fixtures目錄中,除了預置的fixture_admin.py,可以繼續添加團隊成員的fixture:

新添加的fixture_your_name.py需要到根目錄的conftest.py中註冊才能生效:

# Import fixtures
exec("from .fixtures.fixture_admin import *")
exec("from .fixtures.fixture_your_name import *")

conftest.py模組中建議全部定義成fixture,不對外提供function。

為了避免命名衝突和程式碼跟蹤,團隊成員的公共函數命名建議加上_yourname後綴。

訪問MySQL資料庫

首先在fixtures\fixture_admin.py中修改mysql_engine

"mysql_engine": mysql_engine("127.0.0.1",  # host
                             "2306",  # port
                             "root",  # username
                             "123456",  # password
                             "test")  # db_name

依次填寫主機名、埠、用戶名、密碼、資料庫名。

接著使用pandas來訪問資料庫,tests\mysql_test.py預置了示例程式碼:

from loguru import logger


def test_mysql(pd, env_vars):
    logger.info(pd.read_sql("select 1 from dual", env_vars.mysql_engine))

返回的數據可以通過data["列名"]["行號"] 的方式讀取。

如果想在console中以表格方式顯示錶數據,可以使用tep.dao.print_db_table()函數,如:

from loguru import logger
from tep.dao import print_db_table


def test_mysql(pd, env_vars):
    data = pd.read_sql("select 1 from dual", env_vars.mysql_engine)
    logger.info(print_db_table(data))

第三方包集成說明

tep使用了Poetry來管理包和依賴:

poetry

目前已集成:

# 造測試數據
faker = "^4.1.1"
# 提取JSON數據
jmespath = "^0.10.0"
# 屏蔽HTTPS警告
urllib3 = "^1.25.9"
# HTTP/HTTPS請求
requests = "^2.24.0"
# HTML測試報告
allure-pytest = "^2.8.16"
allure-python-commons = "^2.8.16"
# 列印日誌
loguru = "^0.5.1"
# 訪問資料庫
pandas = "^1.1.0"
# 配置文件
pyyaml = "^5.3.1"
# 為pandas訪問資料庫提供engine
sqlalchemy = "^1.3.22"
# 把資料庫表列印成表格
texttable = "^1.6.3"
# 支援sqlalchemy使用
pymysql = "^0.10.1"

東方說

最早寫這個工具的想法是以項目工程方式使用pytest,並結合第三方包完成介面自動化落地。如果你也有類似的想法,那麼可以參考tep的做法。tep用戶手冊是針對於tep工具本身的使用說明,不包含pytest框架搭建和基本使用,如果想入門pytest並深度學習,可以閱讀我寫的pytest系列文章,共8篇。tep的最新版本是0.5.3,還不夠穩定,也存在bug,我會堅持維護下去,既是實用工具,也是技術沉澱。對tep有任何建議或問題,歡迎公眾號後台回復「加群」討論哦:

參考資料:

源碼 //github.com/dongfanger/tep

Tags: