数据驱动开发软件测试脚本

简介: 今天刚提交了我的新作《带着ChatGPT玩转软件开发》给出版社,在写作期间跟着ChatGPT学到许多新知识。下面分享数据驱动开发软件测试脚本。

今天刚提交了我的新作《带着ChatGPT玩转软件开发》给出版社,在写作期间跟着ChatGPT学到许多新知识。下面分享数据驱动开发软件测试脚本。

一个注册页面,需要填写下面4项:账号、密码、手机和Email。

账号(唯一,支持字母、数字,长度5-20)。
密码(长度5-30,必须包含大小写字母、数字和特殊字符)。
手机号(唯一,符合中国的手机格式)。
Email(唯一,符合有效邮箱国际格式)。
1.对API脚本优化

API测试用例如下。

TC-001:测试有效的账号(5-20位字母或数字),测试成功。
TC-002:测试账号长度不足(少于5位,恰好为4位)显示错误信息'账号必须是5-20位字母或数字'。
TC-003:测试账号长度超出(超过20位,恰好为21位)显示错误信息'账号必须是5-20位字母或数字'。
TC-004:测试账号长度正好为5,测试成功,进入成功页面。
TC-005:测试账号长度正好为20,测试成功,进入成功页面。
TC-006:测试账号有特殊字符,显示错误信息'账号必须是5-20位字母或数字'。
TC-007:测试密码为空,显示错误信息'密码应该哈希进行存储'。
TC-008:输入非法的手机号码格式,预期结果:显示错误信息'手机号格式错误'。
TC-009:输入手机号码为空,预期结果:显示错误信息'手机号格式错误'。
TC-010:输入非法的邮箱格式,预期结果:显示错误信息'邮箱格式错误'。
TC-011:输入邮箱为空,预期结果:显示错误信息'邮箱格式错误'。
作为一个用Python requests库写一个API接口程序,一般这样写。

公共类Util.py

# -*- coding: utf-8 -*-
import pymysql
import re
import hashlib
from globals import Config
class ClassDB:
    def initDB(self):
        host = 'localhost'
        user = 'root'
        password = '123456'
        database = 'ebusiness'
        return pymysql.connect(host=host, user=user, password=password, database=database, charset='utf8')
    def execute_query(self, query, params=None):
        connection = self.initDB()
        try:
            with connection.cursor() as cursor:
                cursor.execute(query, params)
                connection.commit()
                return cursor.fetchall()
        finally:
            connection.close()
    def init_db(self):
        self.execute_query("DELETE FROM code")
        self.execute_query("DELETE FROM password")
        self.execute_query("DELETE FROM user")
    #用于测试之前插入数据(如setup测试场景)
    #默认数据
    #username=Config.VALID_USERNAME
    #password=Config.VALID_PASSWORD
    def init_login(self, username, password):
        username = username or Config.VALID_USERNAME
        password = HASH.hash_password(password or Config.VALID_PASSWORD)
        self.execute_query("INSERT INTO user (username, password, phone, email) VALUES (%s, %s, %s, %s)",
                           (username, password,   Config.CONTRACT_PHONE, Config.CONTRACT_EMAIL))
    # 关闭数据库连接
    def closedb(self,connection):
        try:
            connection.close()
        except MySQLError as e:
            print(f"数据库关闭失败: {e}")
class CSRF:
    def get_csrf(html):
        pattern = r'input[^>]+value="([^"]+)"'
        # 使用 re.search 查找匹配
        match = re.search(pattern, html)
        # 提取并打印 value 值
        if match:
            csrftoken_value = match.group(1)
            return csrftoken_value
        else:
            return "未找到 csrftoken"
class HASH:
    #对字符串仅更新SHA256散列
    def hash_password(password):
        """对密码进行SHA256散列"""
        return hashlib.sha256(password.encode('utf-8')).hexdigest()

测试文件Test_Register_1.py

# -*- coding: utf-8 -*-
import requests
import unittest
import hashlib
from Util import ClassDB
from Util import CSRF
from Util import HASH
class TestUserRegistrationAPI(unittest.TestCase):
    #注册接口的URL
    REGISTER_URL="http://127.0.0.1:8080/CharGPTEbusiness/jsp/RegisterPage.jsp"
    def setUp(self):
        self.session = requests.Session()
        response = self.session.get(self.REGISTER_URL)
        self.csrf = CSRF.get_csrf(response.text)
        self.token = {
   "csrftoken": self.csrf}
        self.db = ClassDB()
        self.db.init_db()  # 确保每个测试开始前数据库是干净的
    def tearDown(self):
        self.db.init_db()
    def test_valid_username(self):
        """TC-001:测试有效的账号(5-20位字母或数字)"""
        data={
   
            "csrftoken": self.csrf,
            "username":"validUser123",
            "password":HASH.hash_password("Valid123!"),
            "phone":"13812345678",
            "email":"test@example.com"
        }
        response=requests.post(self.REGISTER_URL,data=data,cookies=self.token)
        self.assertEqual(response.status_code,200)
        self.assertIn("<title>登录页面</title>",response.text)
    def test_username_too_short(self):
        """TC-002:测试账号长度不足(少于5位,恰好为4位)"""
        data={
   
            "csrftoken": self.csrf,
            "username":"usr2",
            "password":HASH.hash_password("Valid123!"),
            "phone":"13812345678",
            "email":"test@example.com"
        }
        response=requests.post(self.REGISTER_URL,data=data,cookies=self.token)
        self.assertEqual(response.status_code,200)
        self.assertIn("账号必须是5-20位字母或数字",response.text)
    def test_username_too_long(self):
        """TC-003:测试账号长度超出(超过20位,恰好为21位)"""
        data={
   
            "csrftoken": self.csrf,
            "username":"user12345678901234567",
            "password":HASH.hash_password("Valid123!"),
            "phone":"13812345678",
            "email":"test@example.com"
        }
        response=requests.post(self.REGISTER_URL,data=data,cookies=self.token)
        self.assertEqual(response.status_code,200)
        self.assertIn("账号必须是5-20位字母或数字",response.text)
    def test_valid_username_length_5(self):
        """TC-004:测试账号长度正好为5"""
        data={
   
            "csrftoken": self.csrf,
            "username":"User5",
            "password":HASH.hash_password("Valid123!"),
            "phone":"13812345678",
            "email":"test@example.com"
        }
        response=requests.post(self.REGISTER_URL,data=data,cookies=self.token)
        self.assertEqual(response.status_code,200)
        self.assertIn("<title>登录页面</title>",response.text)
    def test_valid_username_length_20(self):
         """TC-005:测试账号长度正好为20"""
         data={
   
            "csrftoken": self.csrf,
            "username":"User5User5User5User5",
            "password":HASH.hash_password("Valid123!"),
            "phone":"13812345678",
            "email":"test@example.com"
        }
         response=requests.post(self.REGISTER_URL,data=data,cookies=self.token)
         self.assertEqual(response.status_code,200)
         self.assertIn("<title>登录页面</title>",response.text)
    def test_usename_include_spec_char(self):
        """TC-006:测试账号有特殊字符,显示错误信息'账号必须是5-20位字母或数字''"""
        data={
   
            "csrftoken": self.csrf,
            "username":"valid@User",
            "password":HASH.hash_password("Valid123!"),
            "phone":"12345", 
            "email":"invalid@example.com"
        }
        response=requests.post(self.REGISTER_URL,data=data,cookies=self.token)
        self.assertEqual(response.status_code,200)
        self.assertIn("账号必须是5-20位字母或数字",response.text)
    def test_password_is_null(self):
        """TC-007: 测试密码为空,显示错误信息'密码应该哈希进行存储'"""
        data={
   
            "csrftoken": self.csrf,
            "username":"validUser123",
            "password":"",
            "phone":"13681732596", 
            "email":"invalid@example.com"
        }
        response=requests.post(self.REGISTER_URL,data=data,cookies=self.token)
        self.assertEqual(response.status_code,200)
        self.assertIn("密码应该哈希进行存储",response.text)
    def test_invalid_phone(self):
        """TC-008:输入非法的手机号码格式,预期结果:显示错误信息'手机号格式错误'。"""
        data={
   
            "csrftoken": self.csrf,
            "username":"validUser123",
            "password":HASH.hash_password(""),
            "phone":"23111223344",
            "email":"test@example.com"
        }
        response=requests.post(self.REGISTER_URL,data=data,cookies=self.token)
        self.assertEqual(response.status_code,200)
        self.assertIn("手机号必须符合中国手机号码格式",response.text)
    def test_phone_is_null(self):
        """TC-009:输入手机号码为空,预期结果:显示错误信息'手机号格式错误'。'"""
        data={
   
            "csrftoken": self.csrf,
            "username":"validUser123",
            "password":HASH.hash_password("Valid123!"),
            "phone":"",
            "email":"test@example.com"
        }
        response=requests.post(self.REGISTER_URL,data=data,cookies=self.token)
        self.assertEqual(response.status_code,200)
        self.assertIn("手机号必须符合中国手机号码格式",response.text)
    def test_invalid_mail(self):
        """TC-010:输入非法的邮箱格式,预期结果:显示错误信息'邮箱格式错误'。'"""
        data={
   
            "csrftoken": self.csrf,
            "username":"validUser123",
            "password":HASH.hash_password("Valid123!"),
            "phone":"13645678899",
            "email":"test@example"
        }
        response=requests.post(self.REGISTER_URL,data=data,cookies=self.token)
        self.assertEqual(response.status_code,200)
        self.assertIn("Email格式不正确",response.text)
    def test_mail_is_null(self):
        """TC-011:输入邮箱为空,预期结果:显示错误信息'邮箱格式错误'。'"""
        data={
   
            "csrftoken": self.csrf,
            "username":"validUser123",
            "password":HASH.hash_password("Valid123!"),
            "phone":"13645678899",
            "email":"test@example"
        }
        response=requests.post(self.REGISTER_URL,data=data,cookies=self.token)
        self.assertEqual(response.status_code,200)
        self.assertIn("Email格式不正确",response.text)
if __name__=="__main__":
      unittest.main()

我们建立globals.py,定义公共数据

class Config:
    REGISTER_URL="http://127.0.0.1:8080/CharGPTEbusiness/jsp/RegisterPage.jsp"
    VALID_USERNAME="validUser123"
    VALID_PASSWORD="Valid123!"
    VALID_PHONE="13812345677"
    VALID_EMAIL="valid@example.com"
    SHORT_USERNAME="usr2"
    LONG_USERNAME="user12345678901234567"
    SHORT_PLUS1_USERNAME="usr12"
    LONG_REDUCE1_USERNAME="user1234567890123456"
    WITCH_SPEC_CHAR_USERNAME="user@123"
    ZERO_SIZE_STRING=""
    INVALID_PHONE="23144556677"
    INVALID_EMAIL="a@b"

定义测试文件Test_Register_2.py。

# -*- coding: utf-8 -*-
import requests
import unittest
import hashlib
from Util import ClassDB
from Util import CSRF
from Util import HASH
from parameterized import parameterized
from globals import Config
MESSAGES={
   
    "LOGIN_PAGE":"<title>登录页面</title>",
    "INVALID_USERNAME":"账号必须是5-20位字母或数字",
    "INVALID_PHONE":"手机号必须符合中国手机号码格式",
    "INVALID_EMAIL":"Email格式不正确",
    "NO_HASH":"密码应该哈希进行存储",
}
class TestUserRegistrationAPI(unittest.TestCase):
    def setUp(self):
        self.session = requests.Session()
        response = self.session.get(Config.REGISTER_URL)
        self.csrf = CSRF.get_csrf(response.text)
        self.token = {
   "csrftoken": self.csrf}
        self.db = ClassDB()
        self.db.init_db()  # 确保每个测试开始前数据库是干净的
    def tearDown(self):
        self.db.init_db()
    def _prepare_registration_data(self, username, password, phone, email, expected_message):
        if expected_message!="密码应该哈希进行存储":
            password = HASH.hash_password(password)
        return {
   
                "csrftoken": self.csrf,
                "username": username,
                "password": password,
                "phone": phone,
                 "email": email,
            }
    @parameterized.expand([
    (Config.VALID_USERNAME,Config.VALID_PASSWORD,Config.VALID_PHONE,Config.VALID_EMAIL,MESSAGES["LOGIN_PAGE"]),
    (Config.SHORT_USERNAME,Config.VALID_PASSWORD,Config.VALID_PHONE,Config.VALID_EMAIL,MESSAGES["INVALID_USERNAME"]),
    (Config.LONG_USERNAME,Config.VALID_PASSWORD,Config.VALID_PHONE,Config.VALID_EMAIL,MESSAGES["INVALID_USERNAME"]),
    (Config.SHORT_PLUS1_USERNAME,Config.VALID_PASSWORD,Config.VALID_PHONE,Config.VALID_EMAIL,MESSAGES["LOGIN_PAGE"]),
    (Config.LONG_REDUCE1_USERNAME,Config.VALID_PASSWORD,Config.VALID_PHONE,Config.VALID_EMAIL,MESSAGES["LOGIN_PAGE"]),
    (Config.WITCH_SPEC_CHAR_USERNAME,Config.VALID_PASSWORD,Config.VALID_PHONE,Config.VALID_EMAIL,MESSAGES["INVALID_USERNAME"]),
    (Config.VALID_USERNAME,Config.ZERO_SIZE_STRING,Config.VALID_PHONE,Config.VALID_EMAIL,MESSAGES["NO_HASH"]),
    (Config.VALID_USERNAME,Config.VALID_PASSWORD,Config.INVALID_PHONE,Config.VALID_EMAIL,MESSAGES["INVALID_PHONE"]),
    (Config.VALID_USERNAME,Config.VALID_PASSWORD,Config.ZERO_SIZE_STRING,Config.VALID_EMAIL,MESSAGES["INVALID_PHONE"]),
    (Config.VALID_USERNAME,Config.VALID_PASSWORD,Config.VALID_PHONE,Config.INVALID_EMAIL,MESSAGES["INVALID_EMAIL"]),
    (Config.VALID_USERNAME,Config.VALID_PASSWORD,Config.VALID_PHONE,Config.ZERO_SIZE_STRING,MESSAGES["INVALID_EMAIL"]),
    ])
    def test_register(self,username,password,phone,email,expected_message):
        """TC-001:测试有效的账号(5-20位字母或数字),测试成功。"""
        """TC-002:测试账号长度不足(少于5位,恰好为4位)显示错误信息'账号必须是5-20位字母或数字'。"""
        """TC-003:测试账号长度超出(超过20位,恰好为21位)显示错误信息'账号必须是5-20位字母或数字'。"""
        """TC-004:测试账号长度正好为5,测试成功,进入成功页面。"""
        """TC-005:测试账号长度正好为20,测试成功,进入成功页面。"""
        """TC-006:测试账号有特殊字符,显示错误信息'账号必须是5-20位字母或数字'。"""
        """TC-007:测试密码为空,显示错误信息'密码应该哈希进行存储'。"""
        """TC-008:输入非法的手机号码格式,预期结果:显示错误信息'手机号格式错误'。"""
        """TC-009:输入手机号码为空,预期结果:显示错误信息'手机号格式错误'。"""
        """TC-010:输入非法的邮箱格式,预期结果:显示错误信息'邮箱格式错误'。"""
        """TC-011:输入邮箱为空,预期结果:显示错误信息'邮箱格式错误'。"""
        """TC-012:没有CSRF Token,预期结果:返回注册页面。"""
        data=self._prepare_registration_data(username,password,phone,email, expected_message)
        response=self.session.post(Config.REGISTER_URL, data=data, cookies=self.token)
        response.raise_for_status()#直接抛出异常
        self.assertEqual(response.status_code, 200)
        self.assertIn(expected_message, response.text)
if __name__=="__main__":
        unittest.main()

由于post数据均为

{
   
     "csrftoken":self.csrf,
     "username":username,
     "password":password,
     "phone":phone,
     "email":email,
}

可以独立出一个函数。

def _prepare_registration_data(self, username, password, phone, email, expected_message):
        if expected_message!="密码应该哈希进行存储":
            password = HASH.hash_password(password)
        return {
   
                "csrftoken":self.csrf,
                "username":username,
                "password":password,
                "phone":phone,
                 "email":email,
            }

另外在主程序中使用@parameterized.expand用于测试数据参数化。

错误数据封装在字典类型MESSAGES变量中。

2.对GUI脚本优化

GUI测试用例如下。

GTC-001-账号有效性测试:输入有效账号(5-20位字母或数字),预期结果,显示:"注册成功"。
GTC-002-密码长度不足:密码长度少于5位(恰好为4位),预期结果为显示错误信息:"密码必须是5-30位,包含大小写字母、数字和特殊字符"。
GTC-003-密码长度超出测试:输入超过30位的密码(恰好为31位),预期结果为显示错误信息:"密码必须是5-30位,包含大小写字母、数字和特殊字符"。
GTC-004-密码确认一致性测试:输入不一致的密码与确认密码,预期结果为显示错误信息:"密码确认不一致"。
GTC-005-手机号格式错误测试:输入非法手机号码格式,预期结果为显示错误信息:"手机号格式错误"。
GTC-006-Email格式错误测试:输入非法手机号码格式,预期结果为显示错误信息:"Email格式错误"。
GTC-007-密码长度为5位:密码长度恰好为5位,预期结果,显示:"注册成功"。
GTC-008-密码长度为30位:密码长度恰好为30位,预期结果,显示:"注册成功"。
GTC-009-密码不包含特殊字符:密码不包含特殊字符,预期结果为显示错误信息:"密码必须是5-30位,包含大小写字母、数字和特殊字符"。
GTC-010-密码不包含小写字符:密码不包含小写字符,预期结果为显示错误信息:"密码必须是5-30位,包含大小写字母、数字和特殊字符"。
GTC-011-密码不包含大写字符:密码不包含大写字符,预期结果为显示错误信息:"密码必须是5-30位,包含大小写字母、数字和特殊字符"。
GTC-012-密码不包含数字字符:密码不包含数字字符,预期结果为显示错误信息:"密码必须是5-30位,包含大小写字母、数字和特殊字符"。
一般的测试用例如下:

Test_Register_GUI_1.py
import pytest
from playwright.sync_api import Page
#测试类
class TestUserRegistrationAPI:
    @pytest.fixture(scope="module")
    def setup(self):
        with sync_playwright()as p:
            self.browser=p.chromium.launch(headless=False)#设为 True 可以在后台运行
            self.page=self.browser.new_page()
            self.page.goto('http://127.0.0.1:8080/CharGPTEbusiness/jsp/RegisterPage.jsp')#请替换为你的HTML文件路径
            yield
            self.browser.close()
    def test_valid_username(self,setup):
        '''GTC-001-账号有效性测试'''
        page.goto(REGISTER_URL)
        page.fill('input[name="username"]','validUser123')
        page.fill('input[name="password"]','ValidPass123!')
        page.fill('input[name="confirmPassword"]','ValidPass123!')
        page.fill('input[name="phone"]','13800138000')
        page.fill('input[name="email"]','test@example.com')
        page.click('button[type="submit"]')
        #检查注册是否成功(这里需要根据实际页面反馈调整)
        assert page.locator('text=注册成功').is_visible()
    def test_invaild_password(self,setup):
        '''GTC-002-密码长度不足测试(恰好为4位)'''
        page.goto(REGISTER_URL)
        page.fill('input[name="username"]','testUser')
        page.fill('input[name="password"]','Va@3')
        page.fill('input[name="confirmPassword"]','Va@3')
        page.fill('input[name="phone"]','13800138000')
        page.fill('input[name="email"]','test@example.com')
        page.click('button[type="submit"]')
        #检查错误信息
        assert page.locator('text=密码必须包含大小写字母、数字和特殊字符,长度在5-30之间').is_visible()
    def test_password_length_too_long(self,setup):
        '''GTC-003-密码长度超出测试(恰好为31位)'''
        page.goto(REGISTER_URL)
        page.fill('input[name="username"]','testUser')
        page.fill('input[name="password"]','iLongpassword12@Longpassword12@')
        page.fill('input[name="confirmPassword"]','iLongpassword12@Longpassword12@')
        page.fill('input[name="phone"]','13800138000')
        page.fill('input[name="email"]','test@example.com')
        page.click('button[type="submit"]')
        #检查错误信息
        assert page.locator('text=密码必须包含大小写字母、数字和特殊字符,长度在5-30之间').is_visible()
    def test_password_consistency(self,setup):
        '''GTC-004-输入密码与确认密码确保不一致性'''
        page.goto(REGISTER_URL)
        page.fill('input[name="username"]','testUser')
        page.fill('input[name="password"]','ValidPass123!')
        page.fill('input[name="confirmPassword"]','validPass123!')#不一致密码
        page.fill('input[name="phone"]','13800138000')
        page.fill('input[name="email"]','test@example.com')
        page.click('button[type="submit"]')
        #检查错误信息
        assert page.locator('text=密码确认不一致').is_visible()
    def test_invalid_phone_format(self,setup):
        '''GTC-005-手机号格式错误测试:'''
        page.goto(REGISTER_URL)
        page.fill('input[name="username"]','testUser')
        page.fill('input[name="password"]','ValidPass123!')
        page.fill('input[name="confirmPassword"]','ValidPass123!')
        page.fill('input[name="phone"]','12345')#非法手机号
        page.fill('input[name="email"]','test@example.com')
        page.click('button[type="submit"]')
        #检查错误信息
        assert page.locator('text=请输入有效的中国手机号').is_visible()
    def test_invalid_phone_format(self,setup):
        '''GTC-006-Emai格式错误测试:'''
        page.goto(REGISTER_URL)
        page.fill('input[name="username"]','testUser')
        page.fill('input[name="password"]','ValidPass123!')
        page.fill('input[name="confirmPassword"]','ValidPass123!')
        page.fill('input[name="phone"]','13455667788')#非法手机号
        page.fill('input[name="email"]','test@example')
        page.click('button[type="submit"]')
        #检查错误信息
        assert page.locator('text=邮箱格式错误').is_visible()
    def test_password_length_5(self,setup):
        '''GTC-007-密码长度为5位:密码长度恰好为5位:'''
        page.goto(REGISTER_URL)
        page.fill('input[name="username"]','validUser123')
        page.fill('input[name="password"]','Ab@12')
        page.fill('input[name="confirmPassword"]','Ab@12')
        page.fill('input[name="phone"]','13800138000')
        page.fill('input[name="email"]','test@example.com')
        page.click('button[type="submit"]')
        #检查注册是否成功(这里需要根据实际页面反馈调整)
        assert page.locator('text=注册成功').is_visible()
    def password_length_30(self,setup):
        '''GTC-008-密码长度为30位:密码长度恰好为30位。'''
        page.goto(REGISTER_URL)
        page.fill('input[name="username"]','validUser123')
        page.fill('input[name="password"]','Ab@1212345Ab@1212345Ab@1212345Ab@1212345')
        page.fill('input[name="confirmPassword"]',' Ab@1212345Ab@1212345Ab@1212345Ab@1212345')
        page.fill('input[name="phone"]','13800138000')
        page.fill('input[name="email"]','test@example.com')
        page.click('button[type="submit"]')
        #检查注册是否成功(这里需要根据实际页面反馈调整)
        assert page.locator('text=注册成功').is_visible()
    def test_password_no_include_other_char(self,setup):
        '''GTC-009-密码不包含特殊字符:密码不包含特殊字符'''
        page.goto(REGISTER_URL)
        page.fill('input[name="username"]','testUser')
        page.fill('input[name="password"]','Abc123')
        page.fill('input[name="confirmPassword"]','Abc123')
        page.fill('input[name="phone"]','13800138000')
        page.fill('input[name="email"]','test@example.com')
        page.click('button[type="submit"]')
        #检查错误信息
        assert page.locator('text=密码必须包含大小写字母、数字和特殊字符,长度在5-30之间').is_visible()
    def test_duplicate_no_include_lowercase_char(self,setup):
        '''GTC-010-密码不包含小写字符:密码不包含小写字符''' 
        page.goto(REGISTER_URL)
        page.fill('input[name="username"]','testUser')
        page.fill('input[name="password"]','A@@123')
        page.fill('input[name="confirmPassword"]','A@@123')
        page.fill('input[name="phone"]','13800138000')
        page.fill('input[name="email"]','test@example.com')
        page.click('button[type="submit"]')
        #检查错误信息
        assert page.locator('text=密码必须包含大小写字母、数字和特殊字符,长度在5-30之间').is_visible()
    def test_no_include_capital_char(self,setup):
        '''GTC-011-密码不包含大写字符:密码不包含大写字符'''
        page.goto(REGISTER_URL)
        page.fill('input[name="username"]','testUser')
        page.fill('input[name="password"]','a@@123')
        page.fill('input[name="confirmPassword"]','a@@123')
        page.fill('input[name="phone"]','13800138000')
        page.fill('input[name="email"]','test@example.com')
        page.click('button[type="submit"]')
        #检查错误信息
        assert page.locator('text=密码必须包含大小写字母、数字和特殊字符,长度在5-30之间').is_visible()
    def test_no_include_capital_digest(self,setup):
        '''GTC-012-密码不包含数字字符:密码不包含数字字符'''
        page.goto(REGISTER_URL)
        page.fill('input[name="username"]','testUser')
        page.fill('input[name="password"]','a@@ABC')
        page.fill('input[name="confirmPassword"]','a@@ABC')
        page.fill('input[name="phone"]','13800138000')
        page.fill('input[name="email"]','test@example.com')
        page.click('button[type="submit"]')
        #检查错误信息
        assert page.locator('text=密码必须包含大小写字母、数字和特殊字符,长度在5-30之间').is_visible()
if __name__=="__main__":
    pytest.main(["-sv", "Test_Register_GUI_1.py"])

下面,我们仍对测试数据参数化,在globals.py中加入

LOGIN_URL=http://127.0.0.1:8080/CharGPTEbusiness/jsp/LoginPage.jsp
    SIMPLE_PASSWORD = "12345" 
    FIVE_LENGTH_PASSWORD = "Ab@12" 
    THIRTY_LENGTH_PASSWORD="Ab@1212345Ab@1212345Ab@1212345Ab@1212345" 
    NOT_INCLUE_OTHER_CHAR_PASSWORD = "Abc123" 
    NOT_INCLUE_LOWERCASE_CHAR_PASSWORD = "A@@123" 
    NOT_INCLUE_CAPITAL_CHAR_PASSWORD = " a@@123" 
    NOT_INCLUE_DIGEST_PASSWORD= " a@@ABC"

测试程序

import pytest
from playwright.sync_api import Page
from Util import ClassDB
import time
from globals import Config
MESSAGES={
   
    "LOGIN_PAGE":"登录",
    "INVALID_PASSWORD": "密码必须包含大小写字母、数字和特殊字符,长度在5-30之间",
    "INVALID_REPASSWORD":"密码确认不一致",
    "INVALID_PHONE":"请输入有效的中国手机号",
    "USERNAME_CONFLICT":"注册用户的用户名必须唯一",
    "PHONE_CONFLICT":"注册用户的手机必须唯一",
    "EMAIL_CONFLICT":"注册用户的邮箱必须唯一",
}

Test_Register_GUI_2.py

class TestUserRegistration:
    @pytest.fixture(autouse=True)
    def setup_and_teardown(self):
        self.db = ClassDB()
        self.db.init_db()
        yield
        self.db.init_db()
    def _fill_registration_form(self, page: Page, username: str, password: str, repassword: str, phone: str, email: str):
        page.fill('input[name="username"]', username)
        page.fill('input[name="password"]', password)
        page.fill('input[name="confirmPassword"]', repassword)
        page.fill('input[name="phone"]', phone)
        page.fill('input[name="email"]', email)
        page.click('button[type="submit"]')
    @pytest.mark.parametrize("username, password, repassword, phone, email, expected_message", [
    (Config.VALID_USERNAME,Config.VALID_PASSWORD,Config.VALID_PASSWORD,Config.VALID_PHONE,Config.VALID_EMAIL,MESSAGES["LOGIN_PAGE"]), #GTC-001-账号有效性测试
    (Config.VALID_USERNAME,Config.SHORT_PASSWORD,Config.SHORT_PASSWORD,Config.VALID_PHONE,Config.VALID_EMAIL,MESSAGES["INVALID_PASSWORD"]), #GTC-002 - 密码长度不足测试
    (Config.VALID_USERNAME,Config.LONG_PASSWORD,Config.LONG_PASSWORD,Config.VALID_PHONE,Config.VALID_EMAIL,MESSAGES["INVALID_PASSWORD"]), #GTC-003 - 密码长度超出测试
    (Config.VALID_USERNAME,Config.VALID_PASSWORD,Config.INVALID_PASSWORD,Config.VALID_PHONE,Config.VALID_EMAIL,MESSAGES["INVALID_REPASSWORD"]), #GTC-004 - 输入密码与确认密码确保不一致性
    (Config.VALID_USERNAME,Config.VALID_PASSWORD,Config.VALID_PASSWORD,Config.INVALID_PHONE,Config.VALID_EMAIL,MESSAGES["INVALID_PHONE"]), #GTC-005 - 手机号格式错误测试
    (Config.VALID_USERNAME,Config.FIVE_LENGTH_PASSWORD,Config.FIVE_LENGTH_PASSWORD,Config.VALID_PHONE,Config.VALID_EMAIL,MESSAGES["LOGIN_PAGE"]), #GTC-009-密码长度为5位:密码长度恰好为5位
    (Config.VALID_USERNAME,Config.THIRTY_LENGTH_PASSWORD,Config.THIRTY_LENGTH_PASSWORD,Config.VALID_PHONE,Config.VALID_EMAIL,MESSAGES["LOGIN_PAGE"]), #GTC-010-密码长度为30位:密码长度恰好为30位
    (Config.VALID_USERNAME,Config.NOT_INCLUE_OTHER_CHAR_PASSWORD,Config.NOT_INCLUE_OTHER_CHAR_PASSWORD,Config.VALID_PHONE,Config.VALID_EMAIL,MESSAGES["INVALID_PASSWORD"]), #GTC-011-密码不包含特殊字符:密码不包含特殊字符
    (Config.VALID_USERNAME,Config.NOT_INCLUE_LOWERCASE_CHAR_PASSWORD,Config.NOT_INCLUE_LOWERCASE_CHAR_PASSWORD,Config.VALID_PHONE,Config.VALID_EMAIL,MESSAGES["INVALID_PASSWORD"]),#GTC-012-密码不包含小写字符:密码不包含小写字符
    (Config.VALID_USERNAME,Config.NOT_INCLUE_CAPITAL_CHAR_PASSWORD,Config.NOT_INCLUE_CAPITAL_CHAR_PASSWORD,Config.VALID_PHONE,Config.VALID_EMAIL,MESSAGES["INVALID_PASSWORD"]), #GTC-013-密码不包含大写字符:密码不包含大写字符
    (Config.VALID_USERNAME,Config.NOT_INCLUE_DIGEST_PASSWORD,Config.NOT_INCLUE_DIGEST_PASSWORD,Config.VALID_PHONE,Config.VALID_EMAIL,MESSAGES["INVALID_PASSWORD"]), #GTC-014-密码不包含数字字符:密码不包含数字字符
        (Config.SPACE_USERNAME,Config.SPACE_PASSWORD,Config.SPACE_PASSWORD,Config.SPACE_PHONE,Config.SPACE_EMAIL,MESSAGES["LOGIN_PAGE"]), #GTC-016-账号、密码、手机、邮箱前后都有密码
    ])
    def test_login(self, page: Page, username, password, repassword, phone, email, expected_message):
        page.goto(Config.REGISTER_URL)
        page.reload()
        self._fill_registration_form(page, username, password, repassword, phone, email)
        if expected_message == "登录":
            assert page.get_by_role("heading", name="登录")
        else:
            assert page.locator('text=' + expected_message).is_visible()
if __name__ == '__main__':
    pytest.main(["-sv", "Test_Register_GUI_2.py"])

这里除了对期望结果封装在变量和使用@pytest.mark.parametrize参数化外,由于对于注册菜单的操作都是一样的,因此将这些操作也分装成一个函数。

def _fill_registration_form(self, page: Page, username: str, password: str, repassword: str, phone: str, email: str):
        page.fill('input[name="username"]', username)
        page.fill('input[name="password"]', password)
        page.fill('input[name="confirmPassword"]', repassword)
        page.fill('input[name="phone"]', phone)
        page.fill('input[name="email"]', email)
        page.click('button[type="submit"]')

这样就有了POM的风格。

目录
相关文章
|
2月前
|
安全 数据管理 测试技术
告别蛮力:让测试数据生成变得智能而高效
告别蛮力:让测试数据生成变得智能而高效
370 120
|
3月前
|
测试技术 Linux
VPS一键测试脚本,无痕体验+自动导出,服务器测试更轻松
NodeQuality 是一款整合 Yabs、IPQuality、NetQuality 等主流 VPS 测试脚本的全能工具,支持一键测试硬件性能、IP属性、网络质量,并新增分享与导出功能。其“无痕测试”设计不安装依赖、不留残留,兼容性强;测试结果自动排版、截图并生成分享链接,极大提升效率。适合需要全面、快速、干净测试 VPS 的用户,是运维和测评的高效利器。
256 3
|
8月前
|
机器学习/深度学习 人工智能 并行计算
AI部署架构:A100、H100、A800、H800、H20的差异以及如何选型?开发、测试、生产环境如何进行AI大模型部署架构?
AI部署架构:A100、H100、A800、H800、H20的差异以及如何选型?开发、测试、生产环境如何进行AI大模型部署架构?
AI部署架构:A100、H100、A800、H800、H20的差异以及如何选型?开发、测试、生产环境如何进行AI大模型部署架构?
|
6月前
|
人工智能 缓存 自然语言处理
别再手搓测试数据了!AE测试数据智造系统揭秘
本文介绍如何通过构建基于大语言模型的测试数据智造Agent,解决AliExpress跨境电商测试中数据构造复杂、低效的问题,推动测试效率提升与智能化转型。
别再手搓测试数据了!AE测试数据智造系统揭秘
|
5月前
|
Web App开发 JavaScript 测试技术
Playwright 极速入门:1 小时搞定环境搭建与首个测试脚本
本文带你1小时快速入门Playwright,完成环境搭建并编写首个测试脚本。Playwright是微软推出的现代化Web自动化测试工具,支持Chromium、Firefox和WebKit三大浏览器引擎,具备跨平台、多语言(Python/JS/Java/C#)特性。其核心优势包括:智能自动等待机制减少失败率、内置录制工具实时生成脚本、多语言灵活选择,以及真移动端设备模拟能力,显著提升测试效率和可靠性。
|
6月前
|
传感器 人工智能 JavaScript
鸿蒙开发:DevEcoTesting中的稳定性测试
DevEcoTesting主要的目的也是用于软件的测试,可以让开发者无需复杂的配置,即可一键执行测试任务,同时提供了测试报告和分析,无论是对于开发者还是测试同学来说,都是一个非常方便的工具。
231 3
鸿蒙开发:DevEcoTesting中的稳定性测试
|
5月前
|
敏捷开发 运维 数据可视化
DevOps看板工具中的协作功能:如何打破开发、测试与运维之间的沟通壁垒
在DevOps实践中,看板工具通过可视化任务管理和自动化流程,提升开发与运维团队的协作效率。它支持敏捷开发、持续交付,助力团队高效应对需求变化,实现跨职能协作与流程优化。
|
5月前
|
运维 jenkins 测试技术
"还在苦等开发部署环境?3步教你用Jenkins拿回测试主动权"
测试工程师最头疼的问题是什么?依赖开发部署环境! 开发延期→测试时间被压缩→紧急上线后BUG频出→测试背锅。传统流程中,测试被动等待部署,效率低下。而Jenkins自动化部署让测试人员自主搭建环境,实现: ✅ 随时触发测试,不再苦等开发 ✅ 部署效率提升10倍,抢回测试时间 ✅ 改善团队协作,减少互相甩锅 学习Jenkins部署能力,成为高效测试工程师,告别被动等待!
|
9月前
|
数据采集 算法 数据安全/隐私保护
【硬件测试】基于FPGA的4ASK调制解调通信系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
本文介绍了基于FPGA的4ASK调制解调系统的硬件测试版本,该系统包括testbench、高斯信道模块和误码率统计模块,并新增了ILA在线数据采集和VIO在线SNR设置功能。通过VIO设置不同SNR(如15dB和25dB),实现了对系统性能的实时监测与调整。4ASK是一种通过改变载波幅度表示数据的数字调制方式,适用于多种通信场景。FPGA平台的高效性和灵活性使其成为构建高性能通信系统的理想选择。
230 17
|
9月前
|
数据采集 算法 数据安全/隐私保护
【硬件测试】基于FPGA的4FSK调制解调通信系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
本文基于之前的文章《基于FPGA的4FSK调制解调系统》,增加了ILA在线数据采集模块和VIO在线SNR设置模块,实现了硬件测试版本。通过VIO设置不同SNR(如10dB和20dB),并展示了ILA采集的数据结果。四频移键控(4FSK)是一种数字调制方法,利用四个不同频率传输二进制数据,具有较高的频带利用率和抗干扰性能。输入的二进制数据分为两组,每组两个比特,对应四个频率f1、f2、f3、f4,分别代表二进制组合00、01、10、11。调制过程中选择相应频率输出,并进行幅度调制以增强抗干扰能力。接收端通过带通滤波器提取信号并还原为原始二进制数据。
236 7