CHORD-X自动化测试脚本编写:Python入门到实战

你是不是刚接触Python,觉得语法学得差不多了,但一遇到实际项目就不知道从哪下手?或者你听说过自动化测试很酷,能省下大量重复劳动,却不知道如何用Python来实现?

今天,咱们就从一个非常具体的实战项目出发——为CHORD-X系统编写API自动化测试脚本。我会带你从最基础的Python语法开始,一步步走到能独立编写一个完整的测试套件。学完这篇,你不仅能巩固Python基础,更能亲手做出一个能自动验证系统功能是否正常的实用工具,成就感直接拉满。

1. 学习目标与环境准备

在开始敲代码之前,我们先明确一下这次实战要达成的目标,并准备好“战场”。

1.1 我们能学到什么?

通过这个教程,你将掌握以下核心技能:

  • Python基础实战:不再是干巴巴的语法,而是在真实项目中运用变量、循环、条件判断和函数。
  • HTTP接口调用:学会使用requests这个强大的库,去跟CHORD-X系统的API“对话”,模拟用户操作。
  • 数据处理:拿到API返回的一串文本(通常是JSON格式),如何从中提取出我们需要的信息进行验证。
  • 测试用例组织:用unittest框架把一个个零散的测试点,组织成结构清晰、可重复运行的测试套件。
  • 完整项目搭建:从零开始,最终得到一个可以一键运行、并给出明确通过/失败报告的自动化测试脚本。

整个学习路径是递进的,每一步都为下一步打下基础,确保你不会掉队。

1.2 搭建Python环境

工欲善其事,必先利其器。首先确保你的电脑上已经安装了Python。

  1. 检查安装:打开你的命令行(Windows上是CMD或PowerShell,Mac/Linux上是Terminal),输入以下命令并回车:

    python --version
    

    或者

    python3 --version
    

    如果显示了类似 Python 3.8.10 的版本信息,恭喜你,已经准备好了。如果提示“找不到命令”,你需要先去Python官网下载并安装最新版本。

  2. 安装必备库:我们这个项目需要三个外部库。在命令行中,一次性安装它们:

    pip install requests
    

    pip是Python的包管理工具,通常随Python一起安装。这条命令会从网络下载requests库并安装。另外两个库json和unittest是Python的标准库,无需额外安装。

环境准备好后,我建议你创建一个专属的文件夹,比如叫做chordx_api_test,用来存放我们接下来写的所有代码文件。

2. Python基础快速回顾

在直接冲向API测试之前,我们花几分钟快速过一下本项目最常用到的Python基础知识。别担心,我们只学马上要用的。

2.1 变量与数据类型

你可以把变量理解成一个贴了标签的盒子,里面可以放各种东西。

# 字符串,用来表示文本,用单引号或双引号包起来
api_url = "https://api.chordx.example.com/login"
username = "test_user"

# 整数和浮点数,用来做计算
timeout_seconds = 5
success_rate = 99.8

# 布尔值,只有True(真)和False(假)两种值,常用于条件判断
is_login_successful = True
need_retry = False

# 列表,用来存一组有序的数据,里面可以是不同类型
test_cases = ["登录", "查询订单", "创建用户"]
status_codes = [200, 404, 500]

# 字典,用来存“键-值”对,通过“键”可以快速找到对应的“值”
request_body = {
    "username": "test_user",
    "password": "secure_password"
}

关键点:等号=是赋值操作,把右边的值放进左边变量名代表的“盒子”里。

2.2 控制流程:让代码“做决定”和“重复劳动”

程序不能只会从上到下执行,还需要根据情况做判断和循环。

条件判断(if/elif/else):根据不同的情况执行不同的代码块。

response_code = 404

if response_code == 200:
    print("接口调用成功!")
elif response_code == 404:
    print("错误:请求的资源不存在。") # 这里会执行
else:
    print("错误:其他未知错误。")

循环(for):让一段代码重复执行多次,特别适合用来遍历列表。

# 遍历测试用例列表
for case in test_cases:
    print(f"正在执行测试用例:{case}")
    # 这里将来可以放调用每个接口的代码
# 输出:
# 正在执行测试用例:登录
# 正在执行测试用例:查询订单
# 正在执行测试用例:创建用户

小技巧:f"字符串{变量}"这种写法叫f-string,可以很方便地在字符串里插入变量的值。

2.3 函数:把代码打包,方便复用

当某段代码(比如登录操作)需要被多次使用时,把它定义成函数是最佳实践。

def greet_user(name):
    """一个简单的函数,向用户问好。"""
    message = f"Hello, {name}!"
    return message

# 使用函数
result = greet_user("Alice")
print(result) # 输出:Hello, Alice!
  • def是定义函数的关键字。
  • greet_user是函数名。
  • (name)是参数,调用函数时需要提供。
  • """文档字符串"""用来描述函数是干什么的,这是个好习惯。
  • return语句指定函数的返回值。

掌握了这些,我们的“弹药”就备齐了,可以开始向API测试进军了。

3. 与CHORD-X API对话:requests库入门

现在进入正题。我们要测试的CHORD-X系统,它的各种功能(登录、查询、下单)都是以API(应用程序编程接口)的形式提供的。简单说,API就是一个规定了格式的“问题”,你按照格式“问”过去,系统就会按照格式“回答”你。我们使用requests库来发送这个“问题”。

3.1 发送你的第一个GET请求

GET请求通常用于从服务器获取数据,比如查询信息。

import requests # 导入requests库

# 假设CHORD-X有一个查询用户信息的接口
url = "https://api.chordx.example.com/user/1001"

# 发送一个最简单的GET请求
response = requests.get(url)

# 打印响应状态码(比如200表示成功,404表示未找到)
print("状态码:", response.status_code)

# 打印服务器返回的文本内容(通常是JSON格式)
print("响应内容:", response.text)

运行这段代码,你就会看到从目标URL返回的数据。这就是自动化测试的第一步:获取数据。

3.2 发送带参数的POST请求

POST请求通常用于向服务器提交数据,比如登录、创建订单。

登录接口通常需要你提交用户名和密码。这些数据需要放在请求的“身体”(body)里,并以JSON格式发送。

import requests
import json # 导入json库,用于处理JSON数据

login_url = "https://api.chordx.example.com/login"

# 准备要提交的数据(一个Python字典)
login_data = {
    "username": "test_user",
    "password": "test_password_123"
}

# 发送POST请求。`json`参数会自动将字典转换为JSON格式并设置正确的请求头
response = requests.post(login_url, json=login_data)

print("登录响应状态码:", response.status_code)
print("登录响应内容:", response.text)

3.3 处理响应结果

服务器返回的response.text是字符串。我们需要把它转换成Python的字典或列表,才能方便地提取其中的字段进行验证。

# 接上例,假设登录成功返回了JSON数据
if response.status_code == 200:
    # 将响应的文本解析为Python字典
    response_json = response.json()
    
    # 现在可以像操作普通字典一样访问数据了
    login_success = response_json.get("success", False) # 获取"success"字段的值,如果不存在则返回False
    user_token = response_json.get("token", "") # 获取登录成功后返回的令牌
    user_role = response_json.get("data", {}).get("role") # 访问嵌套字典
    
    print(f"登录成功: {login_success}")
    print(f"用户令牌: {user_token}")
    print(f"用户角色: {user_role}")
else:
    print(f"登录失败,状态码: {response.status_code}")

重要提示:在实际项目中,密码等敏感信息绝不应该硬编码在代码里。应该使用环境变量或配置文件来管理。这里为了教程清晰才直接写出。

4. 构建你的第一个测试用例

我们已经学会了如何调用单个接口。现在,让我们把一个完整的测试场景(比如“登录并获取用户信息”)封装成一个测试函数。

4.1 测试场景:登录成功后查询用户信息

这个场景包含两个步骤:

  1. 调用登录接口,获取身份验证令牌(token)。
  2. 使用这个token,调用查询用户信息的接口。
import requests

def test_login_and_get_user_info():
    """测试登录并获取用户信息的完整流程。"""
    base_url = "https://api.chordx.example.com"
    
    # 步骤1: 登录
    login_url = f"{base_url}/login"
    login_payload = {"username": "test_user", "password": "test_pass"}
    
    print("步骤1: 正在登录...")
    login_resp = requests.post(login_url, json=login_payload)
    
    # 简单的断言:检查登录是否成功(状态码为200)
    if login_resp.status_code != 200:
        print(f"  登录失败!状态码:{login_resp.status_code}")
        return False # 测试失败
    
    login_data = login_resp.json()
    auth_token = login_data.get("token")
    if not auth_token:
        print("  登录失败!响应中未找到token。")
        return False
    
    print(f"  登录成功,获取到token: {auth_token[:10]}...") # 只打印token前10位
    
    # 步骤2: 使用token查询用户信息
    user_info_url = f"{base_url}/user/me"
    # 在请求头中携带token进行认证
    headers = {"Authorization": f"Bearer {auth_token}"}
    
    print("步骤2: 正在查询用户信息...")
    user_resp = requests.get(user_info_url, headers=headers)
    
    if user_resp.status_code != 200:
        print(f"  查询用户信息失败!状态码:{user_resp.status_code}")
        return False
    
    user_data = user_resp.json()
    username = user_data.get("username")
    print(f"  查询成功,当前用户: {username}")
    
    # 进一步断言:检查返回的用户名是否与登录的一致
    if username == "test_user":
        print("  用户名验证通过!")
        return True # 整个测试场景通过
    else:
        print(f"  用户名验证失败!期望‘test_user’,实际‘{username}’")
        return False

# 执行这个测试函数
if __name__ == "__main__":
    success = test_login_and_get_user_info()
    print(f"\n测试用例执行结果: {'通过' if success else '失败'}")

这个函数已经具备了自动化测试的雏形:执行动作、检查结果(断言)、返回明确的成功/失败状态。

5. 用unittest组织专业的测试套件

当测试用例越来越多时,用一个个独立的函数来管理会变得混乱。Python标准库中的unittest框架能帮我们优雅地组织测试。

5.1 创建你的第一个测试类

我们把相关的测试用例组织在一个类里。

import unittest
import requests

class TestChordXUserAPI(unittest.TestCase):
    """测试CHORD-X用户相关API的测试类。"""
    
    # 这是一个特殊方法,在每个测试方法执行前都会运行,用于准备测试数据
    def setUp(self):
        self.base_url = "https://api.chordx.example.com"
        self.session = requests.Session() # 使用Session可以保持会话,比如自动管理cookies
        self.auth_token = None
        
    # 测试方法必须以‘test_’开头,这样unittest才能自动发现并运行它
    def test_successful_login(self):
        """测试正确的用户名密码能否成功登录。"""
        url = f"{self.base_url}/login"
        data = {"username": "correct_user", "password": "correct_password"}
        
        response = self.session.post(url, json=data)
        
        # unittest提供的断言方法,如果条件不满足,测试会失败并给出信息
        self.assertEqual(response.status_code, 200, "登录接口应返回状态码200")
        
        response_json = response.json()
        self.assertTrue(response_json.get("success"), "登录响应中success字段应为True")
        self.assertIn("token", response_json, "登录响应应包含token字段")
        
        # 将token保存下来,供其他测试方法使用
        self.auth_token = response_json["token"]
        print(f"登录测试通过,token已保存。")
    
    def test_get_user_info_with_token(self):
        """测试使用有效的token能否获取用户信息。"""
        # 先执行登录测试,获取token(注意:测试方法执行顺序默认按方法名排序)
        self.test_successful_login()
        
        # 确保token存在
        if not self.auth_token:
            self.fail("无法获取有效的token,无法继续测试")
            
        url = f"{self.base_url}/user/me"
        headers = {"Authorization": f"Bearer {self.auth_token}"}
        
        response = self.session.get(url, headers=headers)
        self.assertEqual(response.status_code, 200, "获取用户信息接口应返回200")
        
        user_info = response.json()
        self.assertEqual(user_info.get("username"), "correct_user", "返回的用户名应与登录名一致")
        print("获取用户信息测试通过。")
    
    def test_login_with_wrong_password(self):
        """测试使用错误密码登录应失败。"""
        url = f"{self.base_url}/login"
        data = {"username": "correct_user", "password": "wrong_password"}
        
        response = self.session.post(url, json=data)
        # 这里假设密码错误返回401状态码
        self.assertEqual(response.status_code, 401, "密码错误时应返回状态码401")
        
        response_json = response.json()
        self.assertFalse(response_json.get("success", True), "登录响应中success字段应为False")
        print("错误密码登录测试通过。")

# 如果直接运行这个脚本,则执行所有测试
if __name__ == "__main__":
    unittest.main()

将上述代码保存为test_user_api.py,然后在命令行运行:

python test_user_api.py

你会看到unittest框架运行所有test_开头的方法,并输出一个简洁的报告,显示通过了几个测试,失败了几个。

5.2 让测试更健壮:清理与模拟

unittest.TestCase类还提供了tearDown方法,在每个测试方法执行后运行,用于清理资源(如关闭数据库连接)。

def tearDown(self):
    # 例如,如果测试中创建了临时数据,可以在这里清理
    print(f"测试 {self._testMethodName} 执行完毕,进行清理。")
    self.session.close() # 关闭requests Session

对于复杂的测试,你可能会遇到需要模拟(Mock)外部服务的情况。unittest.mock模块非常强大,可以模拟函数、对象的行为,让你的测试不依赖于不稳定的外部系统。这是进阶内容,但知道它的存在很重要。

6. 整合与进阶:构建完整的测试项目

现在,我们把所有知识点串联起来,构建一个更贴近真实项目的测试套件。

6.1 项目结构规划

一个好的项目结构能让代码更清晰。建议这样组织你的测试项目文件夹:

chordx_api_test/
├── config.py          # 配置文件,存放URL、测试账号等
├── common/
│   ├── __init__.py
│   └── api_client.py  # 封装所有API请求的通用客户端
├── tests/
│   ├── __init__.py
│   ├── test_login.py      # 登录模块测试
│   ├── test_user.py       # 用户管理模块测试
│   └── test_order.py      # 订单模块测试
└── run_tests.py       # 主运行脚本

config.py示例:

# 配置文件,方便统一修改
BASE_URL = "https://api.chordx.example.com/v1"
TEST_USERNAME = "auto_test_user"
TEST_PASSWORD = "Test@123456"

common/api_client.py示例:

import requests
from config import BASE_URL

class ChordXAPIClient:
    """封装CHORD-X API调用的客户端。"""
    
    def __init__(self):
        self.session = requests.Session()
        self.base_url = BASE_URL
        self.token = None
    
    def login(self, username, password):
        """登录并保存token。"""
        url = f"{self.base_url}/login"
        payload = {"username": username, "password": password}
        resp = self.session.post(url, json=payload)
        resp.raise_for_status() # 如果状态码不是200,抛出异常
        data = resp.json()
        self.token = data.get("token")
        return data
    
    def get_with_auth(self, endpoint):
        """发送带认证头的GET请求。"""
        headers = {"Authorization": f"Bearer {self.token}"} if self.token else {}
        url = f"{self.base_url}/{endpoint.lstrip('/')}"
        resp = self.session.get(url, headers=headers)
        resp.raise_for_status()
        return resp.json()
    
    # 可以继续封装post_with_auth, put_with_auth等方法

6.2 编写模块化测试

tests/test_login.py示例:

import unittest
from common.api_client import ChordXAPIClient
from config import TEST_USERNAME, TEST_PASSWORD

class TestLoginModule(unittest.TestCase):
    
    def setUp(self):
        self.client = ChordXAPIClient()
    
    def test_valid_login(self):
        """有效账号登录测试。"""
        data = self.client.login(TEST_USERNAME, TEST_PASSWORD)
        self.assertIsNotNone(self.client.token)
        self.assertTrue(data.get("success"))
    
    def test_invalid_password(self):
        """错误密码登录测试。"""
        with self.assertRaises(requests.exceptions.HTTPError): # 期待抛出HTTP错误异常
            self.client.login(TEST_USERNAME, "wrong_password")
    
    def tearDown(self):
        self.client.session.close()

6.3 运行与生成报告

run_tests.py示例:

import unittest
import sys

# 自动发现并加载tests目录下的所有测试
test_loader = unittest.TestLoader()
test_suite = test_loader.discover('tests', pattern='test_*.py')

# 使用TextTestRunner运行测试并输出详细结果
runner = unittest.TextTestRunner(verbosity=2) # verbosity=2 输出详细信息
result = runner.run(test_suite)

# 根据测试结果退出(CI/CD工具常用,0成功,非0失败)
sys.exit(0 if result.wasSuccessful() else 1)

在项目根目录运行python run_tests.py,即可执行所有测试模块。

7. 总结

走完这一趟,我们从零开始,完成了一个完整的Python自动化测试脚本项目。回头看看,你不仅复习了Python变量、循环、函数这些核心语法,更重要的是,你知道了如何用requests库去和真实的Web API交互,如何用json库处理返回的数据,以及如何用unittest框架来组织和管理你的测试用例,让它们变得可维护、可重复执行。

这个为CHORD-X系统编写的测试套件,就是一个非常好的起点。你可以在此基础上,继续为其他功能模块(如订单、商品、支付)添加测试用例,用setUp方法做好测试数据的准备和清理,甚至尝试集成更漂亮的HTML测试报告。

自动化测试的魅力就在于,一旦写好,你就可以随时一键运行,快速知道系统核心功能是否正常,从而腾出时间去进行更深入的探索性测试。希望这个实战项目能成为你Python学习路上的一块坚实跳板。动手去改一改代码,比如换个测试接口,或者增加一些更复杂的断言,遇到问题就查查文档,这才是进步最快的方式。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐