当前位置:首页>python>Python速成(为自动化测试入门精简)

Python速成(为自动化测试入门精简)

  • 2026-08-19 15:41:50
Python速成(为自动化测试入门精简)

软件测试从入门到精通 · 第29篇

如果你准备踏入自动化测试领域,那么Python是自动化测试领域的主流语言。它语法简洁、生态丰富、学习成本低,Selenium、pytest、requests、Appium等主流测试工具对Python均有良好支持。

但很多Python教程的问题是太全面,一上来就从计算机原理讲到设计模式,新手学了两周还没写到第一个测试脚本。所以,本文只讲测试工作中真正会用到的东西,够用即可,需要时再深入学习。

本文假设你有基本的编程概念(比如知道什么是变量),如果尚未接触也不必担心,每个知识点都会附上简短代码示例。


一、变量与数据类型

Python是动态类型语言,变量不需要声明类型,直接赋值即可。

1.1 字符串(str)

字符串是测试中常用的数据类型,URL、页面标题、元素文本、断言信息,都属于字符串类型。Python提供了丰富的字符串操作方法,以下是一些常用的。

# 字符串的四种写法url = "https://www.example.com"       # 双引号title = '登录页面'                      # 单引号(效果一样)html = """<div>    <p>多行文本用三引号</p></div>"""                               # 三引号可以跨行# 常用操作text = "  Hello Selenium  "print(text.strip())          # "Hello Selenium"—去首尾空格print(text.upper())          # "  HELLO SELENIUM  "—全大写print(text.lower())          # "  hello selenium  "—全小写print("Selenium" in text)    # True — 判断是否包含print(text.replace("Selenium""Playwright"))  # 替换print(text.split())          # ['Hello', 'Selenium']—按空格分割# f-string:测试日志中常用的格式化方式name = "admin"password = "123456"print(f"正在登录,用户名:{name},密码:{password}")# f-string调试语法(Python 3.8+):f"{变量=}"直接打印"变量名=值"print(f"{name=}")       # name='admin'print(f"{password=}")   # password='123456'

1.2 整数与浮点数(int/float)

测试中整数和浮点数主要用于计数、超时设置、价格比较等场景。Python支持类型之间的相互转换,这在解析测试数据时经常用到。

# 整数count = 10retry_times = 3# 浮点数price = 19.99timeout = 30.5# 类型转换(测试中经常用到)num_str = "100"real_num = int(num_str)      # 字符串转整数->100float_num = float("3.14")    # 字符串转浮点数->3.14str_num = str(100)           # 整数转字符串->"100"

1.3 列表(list)

列表是Python较为常用的数据结构,测试数据驱动、元素集合管理都离不开它。下面演示列表的增删改查、切片遍历和推导式等核心操作。

# 创建列表test_cases = ["登录成功""用户名错误""密码为空"]numbers = [12345]mixed = ["admin"123True]     # 可以混放不同类型# 增删改查test_cases.append("验证码错误")    # 末尾追加test_cases.insert(1"密码错误")   # 指定位置插入test_cases.remove("用户名错误")    # 按值删除deleted = test_cases.pop()       # 删除并返回最后一个test_cases[0] = "登录正常"        # 修改指定位置# 切片:列表[起始:结束:步长]print(test_cases[1:3])           # 第2到第3个元素print(test_cases[::-1])          # 倒序# 遍历列表for case in test_cases:    print(f"执行测试用例:{case}")# 列表推导式:一行代码生成列表squares = [x**2 for x in range(10)]   # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

1.4 字典(dict)

字典是键值对结构,测试中用于存储配置、测试数据、请求参数等。与列表相比,字典通过键名(而不是数字索引)来存取数据,代码可读性更高。

# 创建字典test_data = {    "username""admin",    "password""123456",    "expected_title""管理后台"}# 读取print(test_data["username"])            # adminprint(test_data.get("email""无"))     # 无。键不存在时返回默认值# 修改与新增test_data["password"] = "new_pass"      # 修改test_data["remember"] = True            # 新增# 遍历for key, value in test_data.items():    print(f"{key}{value}")# 嵌套结构(测试中常用)test_suite = {    "suite_name""登录模块",    "cases": [        {"id""TC001""title""正常登录""data": {"user""admin""pwd""123"}},        {"id""TC002""title""密码错误""data": {"user""admin""pwd""999"}},    ]}print(test_suite["cases"][0]["data"]["user"])   # admin# 字典合并(Python 3.9+):|运算符,等价于{**a, **b}config_a = {"browser""Chrome""timeout"30}config_b = {"headless"True"timeout"15}   # 重复键:后面覆盖前面merged = config_a | config_b # {'browser': 'Chrome', 'timeout': 15, 'headless': True}

1.5 元组(tuple)

元组是不可变的有序序列,创建后不能增、删、改,适合存储不会变化的常量配置。

# 创建元组browser_types = ("Chrome""Firefox""Edge")screen_size = (19201080)# 元组拆包width, height = screen_sizeprint(f"宽度:{width},高度:{height}")

为什么用元组?

作为字典的键、函数返回多个值、保护数据不被意外修改。


二、运算符与条件判断

2.1 运算符

Python运算符分为几个大类。算术运算符处理数字计算,比较运算符用于断言判断,逻辑运算符组合多个条件,成员运算符检查元素是否在容器中。这些是编写测试逻辑的基础。

# 算术运算符a, b = 103print(a + b)    # 13  加print(a - b)    # 7   减print(a * b)    # 30  乘print(a / b)    # 3.333...  除(浮点数)print(a // b)   # 3   整除print(a % b)    # 1   取余print(a ** b)   # 1000  幂运算# 比较运算符。测试断言的基础print(5 == 5)   # True  等于print(5 != 3)   # True  不等于print(5 > 3)    # True  大于print(5 < 3)    # False 小于print(5 >= 5)   # True  大于等于print(5 <= 3)   # False 小于等于# 逻辑运算符。组合多个条件logged_in = Trueis_admin = Falseprint(logged_in and is_admin)    # False 且print(logged_in or is_admin)     # True  或print(not logged_in)             # False 非# 成员运算符。判断元素是否在容器中print("admin" in ["admin""guest"])        # Trueprint("error" not in "success message")     # True

2.2 条件判断(if-elif-else)

条件判断是编写测试逻辑的核心,例如根据执行结果进行不同的断言。

# 基本结构status_code = 200if status_code == 200:    print("请求成功")elif status_code == 404:    print("页面不存在")elif status_code == 500:    print("服务器内部错误")else:    print(f"未知状态码:{status_code}")# 三元表达式(一行if-else)result = "通过" if status_code == 200 else "失败"# 实战:根据页面元素判断登录结果def check_login(page_source):    if "欢迎回来" in page_source:        return "登录成功"    elif "用户名或密码错误" in page_source:        return "账号密码错误"    elif "验证码错误" in page_source:        return "验证码错误"    else:        return "未知错误"# 嵌套条件response_text = '{"code": 200, "message": "success"}'   # 模拟接口响应内容(JSON格式字符串)if status_code == 200:    if "success" in response_text:        print("操作成功")    else:        print("返回成功但操作未生效")

三、循环

3.1 for循环

for循环用于遍历可迭代对象,在测试中常用于遍历测试数据、元素列表等。除了基本的列表遍历,Python还提供了range()、enumerate()、zip()等辅助函数,让循环更加灵活。

# 遍历列表elements = ["用户名输入框""密码输入框""登录按钮"]for element in elements:    print(f"正在定位:{element}")# 遍历字典config = {"browser""Chrome""timeout"30"headless"True}for key, value in config.items():    print(f"{key} = {value}")# range()函数for i in range(5):              # 0, 1, 2, 3, 4    print(f"第 {i+1} 次重试")for i in range(26):           # 2, 3, 4, 5    print(i)for i in range(0102):       # 0, 2, 4, 6, 8(步长2)    print(i)# enumerate():同时获取索引和值test_cases = ["登录""注册""找回密码"]for index, case in enumerate(test_cases):    print(f"用例 {index+1}{case}")# zip():同时遍历多个列表urls = ["/login""/register""/forgot"]titles = ["登录页面""注册页面""找回密码"]for url, title in zip(urls, titles):    print(f"打开 {url},预期标题:{title}")# break与continuefor case in test_cases:    if case == "注册":        continue          # 跳过注册用例    if case == "找回密码":        break              # 到这就停止    print(f"执行:{case}")

3.2 while循环

while循环在测试中常用于等待、重试等需要满足某个条件才停止的场景。与for循环不同,while不依赖可迭代对象,只依赖条件表达式。

# 基本while循环count = 0while count < 3:    print(f"第 {count+1} 次重试")    count += 1# 实战:重试机制import timedef wait_for_element(driver, locator, timeout=10):    """等待元素出现,最多等待timeout秒"""    start_time = time.time()    while time.time() - start_time < timeout:        try:            element = driver.find_element(*locator)            return element        except Exception:            time.sleep(0.5)    raise TimeoutError(f"等待超时:{locator}")

四、函数

函数是代码复用的基本单位。测试框架中,测试用例本身就是函数。

4.1 基本定义与调用

函数通过def关键字定义。参数可以设置默认值,调用时可以选择按位置传参或按关键字传参,非常灵活。

# 知识点1:用def定义函数。def函数名(参数): 函数体def greet():    print("Hello, Tester!")greet()                               # 知识点2:调用函数。函数名(),无参数就写空括号# 知识点3:有参函数+return。函数用return把结果交还给调用处def login(username, password):    print(f"用户名:{username},密码:{password}")    return f"{username} 登录成功"result = login("admin""123456")     # 知识点4:位置传参。按定义顺序依次传入print(result)                         # result接住了return返回的值# 知识点5:默认参数。定义时给参数赋默认值,调用时可以省略def open_browser(browser="Chrome", headless=False):    print(f"启动 {browser} 浏览器,无头模式:{headless}")open_browser()                          # 知识点6:不传参→全部用默认值(Chrome, False)open_browser("Firefox"True)          # 知识点7:位置传参→按顺序覆盖(Firefox, True)open_browser(headless=True)            # 知识点8:关键字传参→"参数名=值",可只传部分、顺序随意# 知识点9:类型注解(Python 3.5+,3.9+支持内置泛型list[str]/dict[str, int])# 现代Python项目的标准做法,标注参数和返回值类型,提升可读性、IDE提示与静态检查def login(username: str, password: str) -> str:    """登录(带类型注解:参数为str,返回str)"""    return f"{username} 登录成功"

4.2 可变参数

当不确定函数需要接收多少个参数时,可以用*args和**kwargs。*args将多个位置参数打包成元组,**kwargs将多个关键字参数打包成字典。

# 知识点1:*args。形参前加一个*,把任意多个位置参数打包成元组def run_cases(*case_names):    for name in case_names:            # case_names是元组 ("TC001","TC002","TC003")        print(f"执行用例:{name}")run_cases("TC001""TC002""TC003")   # 传几个都行,都会被收进元组# 知识点2:**kwargs。形参前加两个*,把任意多个关键字参数打包成字典def set_config(**kwargs):    for key, value in kwargs.items():  # kwargs是字典 {"browser":"Chrome", ...}        print(f"配置 {key} = {value}")set_config(browser="Chrome", timeout=30, base_url="https://test.com")

4.3 返回值

函数用return返回结果。Python函数可以返回多个值,实际是打包成一个元组,调用时可以用元组拆包分别接收。

# 知识点1:return返回多个值。实际是打包成一个元组返回def get_bounds(element):    x = element.location['x']    y = element.location['y']    width = element.size['width']    height = element.size['height']    return x, y, width, height         # 等价于return (x, y, width, height)# 模拟一个页面元素(实际使用中是Selenium定位到的WebElement)class MockElement:    location = {'x'10'y'20}    size = {'width'800'height'600}some_element = MockElement()# 知识点2:元组拆包。用"变量1, 变量2, ..."按位置接收返回的每个值x, y, w, h = get_bounds(some_element)print(f"元素位置:({x}{y}),尺寸:{w}x{h}")

4.4 lambda表达式

lambda是匿名函数,适合在需要函数对象但逻辑非常简单时使用。测试中常见于sorted排序的key参数、filter/map等场景。

# 知识点1:lambda语法。lambda 参数: 表达式,返回表达式的结果,适合一行能写下的简单逻辑# 下面的key=lambda x: x["duration"]等价于定义函数def f(x): return x["duration"]test_results = [    {"name""TC001""duration"3.2},    {"name""TC002""duration"1.5},    {"name""TC003""duration"4.8},]# 知识点2:sorted的key参数。指定按什么排序,这里按字典中duration的值升序sorted_results = sorted(test_results, key=lambda x: x["duration"])print(sorted_results)                  # 按耗时排序:TC002(1.5)→TC001(3.2)→TC003(4.8)# 知识点3:filter(函数, 列表)。用函数逐个判断,保留返回True的元素numbers = [123456]evens = list(filter(lambda x: x % 2 == 0, numbers))  # 保留偶数->[2, 4, 6]# 知识点4:map(函数, 列表)。用函数逐个转换每个元素doubled = list(map(lambda x: x * 2, numbers))         # 每个数乘2-> [2, 4, 6, 8, 10, 12]

五、类与对象

测试中类常用于封装测试用例、测试数据等对象,比如把一条测试用例抽象成一个类,方便统一管理和复用。不需要深入理解面向对象理论,先掌握类的定义、属性和方法即可。

# 知识点1:用class定义类(类名习惯首字母大写)class TestCase:    """测试用例类"""    # 知识点2:类变量。定义在类里、所有实例共享同一份    category = "功能测试"    # 知识点3:构造方法__init__。创建实例时自动调用,self表示当前这个实例    def __init__(self, case_id, title):        self.case_id = case_id            # 知识点4:实例变量。每个实例各有一份,通过 self 存取        self.title = title        self.status = "未执行"    # 知识点5:方法。类里的函数,第一个参数固定是self,用self.xxx访问实例数据    def run(self):        """执行用例(示例中模拟执行)"""        print(f"正在执行:{self.case_id}{self.title}")        self.status = "通过"              # 在方法内修改实例变量    def report(self):        """返回用例结果"""        return f"[{self.status}{self.case_id} - {self.title}"# 知识点6:实例化。"类名(参数)"创建对象,参数会传给__init__case1 = TestCase("TC001""正常登录")case1.run()                              # 知识点7:调用方法。"实例.方法名()"print(case1.report())case2 = TestCase("TC002""密码错误")     # 每个实例的实例变量互相独立print(case2.report())          # 未执行,状态为"未执行"# 知识点8:继承。"class 子类(父类)",子类自动拥有父类的属性和方法class ApiTestCase(TestCase):    """接口测试用例(继承TestCase)"""    category = "接口测试"                # 知识点9:子类覆盖类变量(重新赋值即可)    # 知识点10:super().__init__(...)。调用父类的构造方法,复用父类初始化逻辑    def __init__(self, case_id, title, method, path):        super().__init__(case_id, title)        self.method = method               # 知识点11:子类新增自己的实例变量        self.path = path    # 知识点12:方法重写。与父类方法同名,子类实例调用时优先用子类的版本    def run(self):        """重写父类方法"""        print(f"发送 {self.method} 请求:{self.path}")        self.status = "通过"api_case = ApiTestCase("TC010""查询用户列表""GET""/api/users")api_case.run()                           # 实际调用的是ApiTestCase自己的run()print(api_case.report())                 # report()未重写,沿用父类的实现print(f"用例分类:{TestCase.category} / {ApiTestCase.category}")  # 类变量可直接用"类名.变量"访问

六、模块与异常处理

6.1 模块导入(import)

Python通过import语句引入其他模块的功能。模块可以是Python标准库(如 time)、第三方库(如selenium)、或你自定义的.py文件。常见的导入方式有以下几种。

# 导入整个模块import timetime.sleep(2)# 导入模块并起别名import selenium.webdriver as wd      # 之后可用wd.Chrome(),效果同from selenium import webdriverfrom selenium.webdriver.common.by import By# 从模块导入特定内容from selenium import webdriverfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as EC# 导入自定义模块(同目录下的py文件)from login_page import LoginPagefrom test_data import user_data# 按目录导入from pages.login_page import LoginPagefrom utils.config import BASE_URL

6.2 异常处理(try-except)

自动化测试中,网络超时、元素找不到、断言失败都是异常。合理处理异常可以提高脚本的健壮性。Python的异常处理包括try、except、else、finally四个子句,以及自定义异常。

# 知识点1:try-except基本结构。把可能出错的代码放try,一旦出错就跳到except处理try:    price = int("19.99")          # "19.99"不是合法的整数字符串,会抛ValueError    print(f"价格:{price}")except Exception as e:    print(f"转换失败:{e}")        # 捕获任意异常,e是错误信息# 知识点2:捕获特定异常。按异常类型分别处理,except从上往下匹配第一个try:    data = {"username""admin"}    print(data["password"])       # 键不存在,抛KeyErrorexcept KeyError:    print("缺少键:password")      # 只处理KeyErrorexcept ValueError:    print("值不合法")except Exception as e:    print(f"未预期的错误:{type(e).__name__} - {e}")# 知识点3:else。try没有异常时才执行else里的代码# 知识点4:finally。无论有没有异常都会执行,是清理资源的固定位置try:    result = 10 / 2               # 正常执行,不会触发exceptexcept ZeroDivisionError:    print("除数不能为零")else:    print(f"计算结果:{result}")    # try成功时执行finally:    print("清理资源")              # 无论是否异常都会执行# 知识点5:自定义异常。继承Exception,用于表达业务上的错误情况class TestDataError(Exception):    """测试数据异常"""    passdef validate_test_data(data):    if "username" not in data:        raise TestDataError("缺少必填字段:username")   # raise主动抛出异常validate_test_data({"password""123"})   # 会抛出TestDataError# 知识点6:安全地取值,键不存在时返回默认值而不是让程序崩溃def safe_get(dict_data, key, default="未找到"):    try:        return dict_data[key]    except KeyError:        return defaultuser = {"username""admin"}print(safe_get(user, "email"))     # 未找到(键不存在,不崩溃)print(safe_get(user, "username"))  # admin

七、文件与数据格式

测试中经常需要读取测试数据文件或写入测试结果日志。

7.1 文本文件

open()加with语句是Python读写文件的标准方式。with会自动管理文件关闭,即使发生异常也能正确释放资源。

# 知识点1:with open(文件名, 模式, 编码) as f,上下文管理器,用完自动关闭文件,即使出异常也会释放资源# 知识点2:模式"w"写入(会覆盖原文件已有内容,文件不存在则创建)# 写入文件with open("test_result.txt""w", encoding="utf-8"as f:    f.write("测试报告\n")    f.write("=" * 40 + "\n")    f.write("用例总数:10\n")    f.write("通过:8\n")    f.write("失败:2\n")# 知识点3:模式"a"追加(在文件末尾续写,不清空原内容,文件不存在则创建)# 追加写入with open("test_log.txt""a", encoding="utf-8"as f:    f.write(f"[2024-01-15 10:30:00] 执行登录用例\n")# 知识点4:模式"r"读取+f.read()一次性读出整个文件内容# 读取整个文件with open("test_result.txt""r", encoding="utf-8"as f:    content = f.read()    print(content)# 知识点5:逐行读取,for line in f按行遍历,line自带结尾换行符# 知识点6:line.strip()去掉每行首尾空白(换行符等);if case_name跳过空行# 逐行读取with open("test_cases.txt""r", encoding="utf-8"as f:    for line in f:        case_name = line.strip()        if case_name:              # 跳过空行            print(f"执行:{case_name}")

7.2 文件模式速查表

r:只读,文件不存在时报错。

w:写入(覆盖),文件不存在时创建新文件。

a:追加,文件不存在时创建新文件。

r+:读写,文件不存在时报错。

b:二进制模式(与上述模式组合使用,如'rb'或'wb')。

7.3 JSON处理

JSON是测试中最常见的数据交换格式,API测试的请求和响应基本都是 JSON。Python内置的json模块提供了dumps(字典→JSON字符串)和 loads(JSON字符串→字典)两种核心方法,以及对应的文件读写方法dump和load。

import json# 知识点1:dumps,Python字典->JSON字符串(用于打印、拼接、传输)# 知识点2:ensure_ascii=False让中文原样输出(否则转成\uXXXX);indent=2缩进美化test_data = {    "username""admin",    "password""123456",    "remember"True,    "roles": ["admin""editor"]}json_str = json.dumps(test_data, ensure_ascii=False, indent=2)print(json_str)# 输出:# {#   "username": "admin",#   "password": "123456",#   "remember": true,#   "roles": [#     "admin",#     "editor"#   ]# }# 知识点3:dump,把字典直接写入JSON文件(dumps返回字符串、dump写入文件,注意多一个s的区别)# 写入JSON文件(dump,生成test_data.json)with open("test_data.json""w", encoding="utf-8"as f:    json.dump(test_data, f, ensure_ascii=False, indent=2)# 知识点4:load,从JSON文件读回字典(dump和load成对,配合文件使用)# 读取JSON文件(load,读回字典)with open("test_data.json""r", encoding="utf-8"as f:    loaded_data = json.load(f)print(loaded_data["username"])        # "admin"print(loaded_data["roles"])           # ['admin', 'editor']# 知识点5:loads,JSON字符串->Python字典(解析接口响应的标准动作)# JSON字符串->Python字典(loads,用于解析接口响应)response = '{"code": 200, "message": "success", "data": {"token": "abc123"}}'data = json.loads(response)print(data["code"])                  # 200print(data["data"]["token"])        # abc123

7.4 CSV处理

CSV是测试数据驱动的常用格式,可以方便地用Excel编辑。Python的csv模块提供了DictReader(将每行读为字典)和writer(写入行数据)两种核心工具。

import csv# 知识点1:csv.writer+writerows,把列表的列表逐行写入文件# 知识点2:newline=""必须加,Windows下不加会在每行后多出空行# 知识点3:第一行为表头,DictReader靠它识别列名# 写入CSV文件(生成test_users.csv,第一行为表头)users = [    ["username""password"],     # 表头,DictReader靠它识别列名    ["admin""123456"],    ["tester""abc123"],]with open("test_users.csv""w", encoding="utf-8", newline=""as f:    writer = csv.writer(f)    writer.writerows(users)# 知识点4:csv.DictReader,把每行读成字典,用表头当键名(row['username']这种取法)# 读取CSV文件with open("test_users.csv""r", encoding="utf-8"as f:    reader = csv.DictReader(f)        # 每行变为字典    for row in reader:        print(f"用户名:{row['username']},密码:{row['password']}")        # 这里执行具体的测试逻辑# 知识点5:数据驱动:遍历行+条件判断+异常处理+字典解包合并def test_login_from_csv(csv_path):    with open(csv_path, "r", encoding="utf-8"as f:        reader = csv.DictReader(f)        results = []        for row in reader:            try:                # 执行登录操作(这里简化演示)                if row["username"and row["password"]:                    result = "通过"                else:                    result = "失败"            except Exception as e:                result = f"异常:{e}"            results.append({**row, "result": result})   # {**row, ...}把result合并进原字典        return results# 调用函数print(test_login_from_csv("test_users.csv"))

八、包管理与综合实战

8.1 pip安装第三方库

Python的强大在于生态,测试中要用到的库基本都通过pip安装。pip是Python的包管理工具,可以安装、查看、卸载第三方库。推荐将项目依赖写入requirements.txt统一管理。

# 基本安装pip install selenium# 安装指定版本pip install selenium==4.47.0# 批量安装(依赖的包写在requirements.txt)pip install -r requirements.txt# 查看已安装的库pip list# 查看某个库的信息pip show selenium# 卸载pip uninstall selenium

测试工程常用的requirements.txt示例:

selenium>=4.47.0pytest>=9.1.1pytest-html>=4.2.0pytest-xdist>=3.8.0pytest-rerunfailures>=16.5requests>=2.34.2webdriver-manager>=4.1.2openpyxl>=3.1.5PyMySQL>=1.2.0allure-pytest>=2.16.0

8.2 综合实战:一个可运行的登录测试脚本

下面将这些知识点整合起来,编写一个纯Python可运行的测试脚本,综合演示:字典配置、函数封装、CSV数据驱动、循环遍历测试用例、条件判断做断言、异常处理、JSON生成测试报告。脚本不依赖浏览器和网络,被测对象是一个模拟登录服务,把前面学的基础知识串成一条完整的测试流程,复制到本地就能跑起来。

配套两个文件(放在同一目录,运行python test_login.py):

  • test_login.py:测试脚本(下方完整代码)。

  • test_users.csv:测试数据(下方给出内容)。

"""综合实战:一个纯Python可运行的登录测试脚本演示:字典配置、函数封装、CSV数据驱动、循环、条件断言、异常处理、JSON报告运行:python test_login.py(需同目录有test_users.csv)"""import csvimport json# ---------- 1.配置数据(字典) ----------CONFIG = {    "csv_path""test_users.csv",       # 测试数据文件    "report_path""test_report.json",  # 报告输出文件}# ---------- 2.被测系统:模拟登录服务 ----------def login(username, password):    """模拟登录接口:admin/123456登录成功,其余返回错误信息"""    if not username or not password:        return {"code"1001"message""用户名或密码不能为空"}    if username == "admin" and password == "123456":        return {"code"0"message""登录成功"}    return {"code"1002"message""用户名或密码错误"}# ---------- 3.测试数据驱动(CSV读取+列表遍历) ----------def load_test_data(csv_path):    """从CSV加载测试数据"""    test_data = []    with open(csv_path, "r", encoding="utf-8-sig"as f:   # utf-8-sig兼容Excel保存的带BOM文件        reader = csv.DictReader(f)        for row in reader:            test_data.append(row)    return test_data# ---------- 4.测试执行引擎(循环+条件断言+异常处理) ----------def run_login_test(test_cases):    """执行登录测试,返回测试结果列表"""    results = []    for case in test_cases:        result = {"case_id"case["id"], "title"case["title"], "status""未知"}        try:            resp = login(case["username"], case["password"])   # 调用被测系统            expected = case.get("expected""success")            if expected == "success":                          # 断言:期望登录成功                if resp["code"] == 0:                    result["status"] = "通过"                else:                    result["status"] = "失败"                    result["error"] = f"期望登录成功,实际:{resp['message']}"            elif expected == "fail":                           # 断言:期望登录失败                if resp["code"] != 0:                    result["status"] = "通过"                    result["actual_message"] = resp["message"]                else:                    result["status"] = "失败"                    result["error"] = "期望登录失败,实际却成功了"        except Exception as e:                                 # 异常处理            result["status"] = "异常"            result["error"] = f"{type(e).__name__}{e}"        results.append(result)    return results# ---------- 5.生成测试报告(JSON写入) ----------def generate_report(results, output_path):    """生成JSON格式的测试报告"""    total = len(results)    passed = sum(1 for r in results if r["status"] == "通过")    failed = sum(1 for r in results if r["status"] == "失败")    error = sum(1 for r in results if r["status"] == "异常")    report = {        "summary": {            "total": total,            "passed": passed,            "failed": failed,            "error": error,            "pass_rate"f"{passed/total*100:.1f}%" if total > 0 else "0%"        },        "details": results    }    with open(output_path, "w", encoding="utf-8"as f:        json.dump(report, f, ensure_ascii=False, indent=2)    print("=" * 50)    print(f"测试完成 | 总计:{total} | 通过:{passed} | 失败:{failed} | 异常:{error}")    print(f"通过率:{report['summary']['pass_rate']}")    print("=" * 50)# ---------- 6.主入口 ----------if __name__ == "__main__":    test_cases = load_test_data(CONFIG["csv_path"])    if not test_cases:        print("没有测试数据,请检查test_users.csv")    else:        results = run_login_test(test_cases)        generate_report(results, CONFIG["report_path"])

test_users.csv 内容(与脚本放在同一目录):

id,title,username,password,expectedTC001,正常登录,admin,123456,successTC002,密码错误,admin,999999,failTC003,空密码,admin,,fail

运行输出(python test_login.py):

==================================================测试完成 | 总计:3 | 通过:3 | 失败:0 | 异常:0通过率:100.0%==================================================

运行后会在同目录生成test_report.json,包含统计摘要和每个用例的详细结果。把这3条用例的expected改成相反值再跑一次,你就能看到失败分支和50%以下的通过率。试着改改数据,理解断言是如何生效的。


写在最后

这篇文章以够用为原则,把测试工作中常用的Python知识点串了一遍。这些不是全部,但足够让你看懂和编写绝大部分自动化测试脚本了。

用一句话总结Python的学习思路:先运行起来,再逐步优化。 不需要先看完一整本教程才开始写测试。把本文的每个代码块复制运行一遍,然后尝试改写参数、修改逻辑,慢慢就熟练了。

下一步,我们将正式进入Selenium WebDriver的世界,用Python驱动浏览器,开始真正意义上的自动化测试。


本文为《软件测试从入门到精通》系列第29篇,本系列持续更新中。

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-08-21 14:40:21 HTTP/2.0 GET : https://f.mffb.com.cn/a/510784.html
  2. 运行时间 : 0.232560s [ 吞吐率:4.30req/s ] 内存消耗:4,802.07kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=9ecefb09afcde291b416bbd18ecb0c0b
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000916s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.001645s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000730s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000677s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.001575s ]
  6. SELECT * FROM `set` [ RunTime:0.000636s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.001576s ]
  8. SELECT * FROM `article` WHERE `id` = 510784 LIMIT 1 [ RunTime:0.001696s ]
  9. UPDATE `article` SET `lasttime` = 1787294421 WHERE `id` = 510784 [ RunTime:0.035383s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 66 LIMIT 1 [ RunTime:0.000736s ]
  11. SELECT * FROM `article` WHERE `id` < 510784 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.001262s ]
  12. SELECT * FROM `article` WHERE `id` > 510784 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.001114s ]
  13. SELECT * FROM `article` WHERE `id` < 510784 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.023334s ]
  14. SELECT * FROM `article` WHERE `id` < 510784 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.001735s ]
  15. SELECT * FROM `article` WHERE `id` < 510784 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.002554s ]
0.236214s