Pythonインターフェイステストコース(4日目)-インターフェイステストフレームワークの実装

ディレクトリ

Pythonインターフェーステストコース(1日目)-Python基本
Pythonインターフェーステストコース(2日目)-
インターフェーステストクイックプラクティスPythonインターフェーステストコース(3日目)-インターフェースセキュリティの検証、パラメータ化、およびアサーション
Pythonインターフェーステストコース(パート1 4日間)-インターフェイステストフレームワークの実装

PDFダウンロード:リンク:https ://pan.baidu.com/s/1x3_LYq23F_1LviGVbRNFXwパスワード:xrcj

その他の学習資料については、作者WeChatを追加してください。

4日目:Pythonインターフェイステストフレームワーク

フレームとは

現在の主流のインターフェーステストソリューション

  • ツールパイ
  • Java Pie
  • Pythonパイ
  • インターフェイスプラットフォーム

フレームタイプ

  • 記録再生
  • データ駆動型
  • 行動主導

フレームワークの階層化と計画

フレームレイヤー

  • プレゼンテーション層:(ユーザーインターフェイス)
  • ビジネスロジックレイヤー:(データの読み取り、構成とアセンブル、リクエストの送信)+実行制御レイヤー(pytest)
  • データレイヤー:(設定の読み取り/データの読み取り/データベース接続/その他(ログ/電子メール))

フレームワークの計画

  • ケース:テストケースディレクトリ
    • ユーザー:(ユーザーモジュール)
      • test_user.py:テストケース
    • case.py:ユースケースのパブリックメソッド
  • data:データファイルディレクトリ
    • test_user_data.xlsx:テストケースデータファイル
  • conf:設定ファイルのディレクトリ
    • default.conf:デフォルトの構成ファイル
  • report:pytestによって生成されたレポートを保存するためのパス
  • ログ:ログ保存パス、日別のログを生成
  • common:共通メソッドディレクトリ
    • config.py:構成ファイルを読み取ります
    • data.py:データファイルの読み取り
    • db.py:データベース接続
    • log.py:ログ構成
    • send_email.py:メール構成の送信

フレームワークの実装

conf / default.conf:プレゼンテーションレイヤープロジェクト構成ファイル

[runtime]
log_level=debug
report_dir=report
log_dir=log
timeout=10

[server]
test = http://127.0.0.1:5000
stage = http://127.0.0.1:6000
prod = http://127.0.0.1:7000

[db_test]
host = localhost
port = 3307
db = api
user = root
passwd = 

[db_stage]

[db_prod]

[email]
server = smtp.sina.com
user = [email protected]
pwd =  ******
subject = Api Test Ressult
receiver = [email protected]

data / test_user_data.xlsx:プレゼンテーションレイヤーのユースケースデータファイル

  • regテーブル(regという名前のシート)
テストケース URL 方法 データ・タイプ データ コード メッセージ
test_reg_normal / api / user / reg / 役職 JSON {"name": "{NAME}"、 "passwd": "123456"} 100000 成功する
  • ログインテーブル(loginという名前のシート)
テストケース URL 方法 データ・タイプ データ ResponseText
test_login_normal / api / user / login / 役職 {"名前": "张三"、 "passwd": "123456"} ログイン成功
  • SQLテーブル(SQLという名前のシート)
checkUser name = {NAME}のユーザーから*を選択します
checkUserPasswd name = {NAME}およびpasswd = {PASSWD}のユーザーから*を選択します

common / config.py:データレイヤー設定ファイルの読み取り

"""
1. 从配置文件中获取各个段信息
2. 返回一个项目的绝对路径
"""
import os
import configparser

# 相对导入包的问题

pro_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


class Config(object):
    def __init__(self, filename="default.conf"):
        self.cf = configparser.ConfigParser()
        self.cf.read(os.path.join(pro_path,"conf",filename))
        
    def get_runtime(self, option):
        return self.cf.get("runtime", option)

    def get_server(self, option):
        return self.cf.get("server", option)

    def get_db_test(self, option):
        return self.cf.get("db_test", option)

    def get_email(self, option):
        return self.cf.get("email",option)

if __name__ == "__main__":
    c = Config()
    print(c.get_runtime("log_level"))
    print(c.get_server("test"))

data.py:データレイヤー-データファイルの読み取り

"""
1. 从Excel中读取接口的数据
2. 读取Sql命令
"""
import xlrd
import sys
import os
sys.path.append("..")
from common.config import pro_path

class Data(object):
    def __init__(self, filename):
        data_file_path = os.path.join(pro_path,"data",filename)   
        self.wb = xlrd.open_workbook("../data/test_user_data.xlsx")

    def get_case(self,sheet_name, case_name):
        sh = self.wb.sheet_by_name(sheet_name)
        for i in range(1, sh.nrows):
            if sh.cell(i,0).value == case_name:
                return sh.row_values(i)

        print("用例名未找到")
        return None

    def get_sql(self, sql_name):
        sh = self.wb.sheet_by_name("SQL")
        for i in range(sh.nrows):
            if sh.cell(i,0).value == sql_name:
                return sh.cell(i,1).value
        print("sql未找到")
        return None

if __name__ == "__main__":
    d = Data("test_user_data.xlsx")
    print(d.get_case("reg","test_reg_normal"))
    print(d.get_sql("checkUser"))

db.py:データレイヤー-データベース接続

"""
1. 从配置文件中读取数据库配置
2. 连接数据库
3. 执行sql并返回所有结果
"""
import sys
import pymysql
sys.path.append("..")
from common.config import Config

class DB(object):
    def __init__(self):
        c = Config()
        self.conn = pymysql.connect(host=c.get_db_test("host"),
                                    port=int(c.get_db_test("port")),
                                    db=c.get_db_test("db"),
                                    user=c.get_db_test("user"),
                                    passwd=c.get_db_test("passwd"),
                                    charset="utf8")

        self.cur = self.conn.cursor()

    def do_sql(self, sql):
        self.cur.execute(sql)
        return self.cur.fetchall()

    def __del__(self):
        self.cur.close()
        self.conn.close()

if __name__ == "__main__":
    db = DB()
    print(db.do_sql("select * from user"))

log.py:データレイヤーログの構成

"""
1. 配置log输出格式 time - loglevel - file - func - line - msg
2. 支持输出到log文件及屏幕
3. 支持返回一个logger,让其他模块调用
"""
import sys
sys.path.append("..")

from common.config import Config, pro_path
import time
import logging
import os

class Log():
    @classmethod
    def config_log(cls):
        cf = Config()
        log_dir = os.path.join(pro_path, cf.get_runtime("log_dir"))
        today = time.strftime("%Y%m%d", time.localtime(time.time()))
        log_file = os.path.join(log_dir, today+".log")

        # 获取一个标准的logger, 配置loglevel
        cls.logger = logging.getLogger()
        cls.logger.setLevel(eval("logging." + cf.get_runtime("log_level").upper()))

        # 建立不同handler
        fh = logging.FileHandler(log_file, mode="a",encoding=‘utf-8’)
        ch = logging.StreamHandler()

        # 定义输出格式
        ft = logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s")
        fh.setFormatter(ft)
        ch.setFormatter(ft)

        # 把定制handler 添加到我们logger
        cls.logger.addHandler(fh)
        cls.logger.addHandler(ch)

    @classmethod
    def get_logger(cls):
        cls.config_log()
        return cls.logger

if __name__ == "__main__":
    l= Log.get_logger()
    l.info("abc")
    l.debug("hello, debug")

send_email.py:データレイヤー-メールサーバー接続

"""
1. 从配置文件中读取stmp配置
2. 从report文件夹下打开report.html,发送邮件
"""
import smtplib
from email.mime.text import MIMEText
import os
import sys
sys.path.append("..")
from common.config import Config, pro_path
from common.log import Log


def send_email(report_name):
    cf = Config()
    logger = Log.get_logger()
    report_file = os.path.join(pro_path, cf.get_runtime("report_dir"),report_name)

    with open(report_file, "rb") as f:
        body = f.read()

    # 格式化email正文
    msg = MIMEText(body, "html", "utf-8")

    # 配置email头
    msg["Subject"] = cf.get_email("subject")
    msg["From"] = cf.get_email("user")
    msg["To"] = cf.get_email("receiver")

    
    # 连接smtp服务器,发送邮件
    smtp = smtplib.SMTP()
    smtp.connect(cf.get_email("server"))
    smtp.login(cf.get_email("user"),cf.get_email("pwd"))
    smtp.sendmail(cf.get_email("user"), cf.get_email("receiver"), msg.as_string())
    print("邮件发送成功")

if __name__ == "__main__":
    send_email("report.html")

case / case.py:ビジネスロジックレイヤー、ユースケースのカプセル化メソッドを実行

"""
1. 加载数据
2. 发送接口
3. 为用例封装一些方法

"""
import sys
sys.path.append("..")
from common.log import Log
from common.config import Config
from common.db import DB
from common.data import Data
import json
import requests


class Case(object):
    def __init__(self):
        self.logger = Log.get_logger()
        self.cf = Config()

    def load_data(self, data_file):
        self.data = Data(data_file)

    def set_env(self, env):
        self.env = env

    def run_case(self, sheet_name, case_name, var={}):
        case_data = self.data.get_case(sheet_name, case_name)

        url = self.cf.get_server(self.env) + case_data[1]
        data = case_data[4].format(**var)
        
        if case_data[3].lower() == "form":
            data = json.loads(data)
            headers = {}
        else:
            headers = {"content-type": "application/json"}

        if case_data[2].lower() == "get":
            resp = requests.get(url=url)
        else:
            resp = requests.post(url=url, headers=headers, data=data)
        return resp.text
        
    def check_response(self):
        pass
    
    def check_db(self, sql_name, vars={}):
        sql = self.data.get_sql(sql_name).format(**vars)
        return self.db.exec_sql(sql)
        

if __name__ == "__main__":
    c = Case()
    c.set_env("test")
    c.load_data("test_user_data.xlsx")
    r = c.run_case("login", "test_login_normal")
    print(r)

ケース/ユーザー/ test_user.py:プレゼンテーションレイヤー:テストケーススクリプト

import sys
import random
import pytest
sys.path.append("../..")
from case.case import Case

case = Case()

def setup_module(module):
    case.set_env('dev')
    case.load_data('test_user_data.xlsx')

def test_login_normal():
    result case.run("login", "test_login_normal")

if __name__ == '__main__':
    pytest.main(["-q", "test_user.py"])

run_all.py:プレゼンテーションレイヤー:すべてのユースケースエントリを実行します

import os
import time
from util.config import Config
from util.e_mail import send_email
import pytest

def main():
    cf = Config()
    report_dir = cf.get_report_dir()
    now = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time()))
    report_name = os.path.join(report_dir, 'report_' + now + '.html')
    pytest.main(["-q", "case", "--html=" + report_name])
    send_email(report_name)

if __name__ == '__main__':
    main()

おすすめ

転載: www.cnblogs.com/superhin/p/12737710.html