论坛系统测试报告

1.项目背景

本项目是基于 SSM 框架(Spring、Spring MVC、MyBatis) 开发的 论坛系统,包括 用户注册、登录、帖子发布、编辑、删除、查看 等功能,同时提供 帖子列表页和详情页 供用户浏览论坛内容。

用户登录后可以 查看自己和其他用户的帖子,并通过系统 记录帖子发布时间、标题、作者信息。论坛支持 用户评论、私信交流、帖子点赞等社交互动功能,提升用户体验。

为了确保系统的稳定性和功能完整性,项目采用 Selenium 自动化测试 进行功能验证,测试内容涵盖:

  • 用户注册与登录:测试不同输入情况下的账号验证逻辑

  • 帖子列表展示:确保帖子加载、排序和分页功能正常

  • 用户信息校验:验证用户个人资料、修改信息的功能

  • 帖子管理:测试帖子发布、编辑、删除是否符合预期

  • 帖子详情页:检查帖子的内容是否正确加载,包括评论、点赞等互动功能

  • 搜索功能:验证用户输入关键词后,搜索结果是否匹配

本项目通过自动化测试覆盖核心功能,确保论坛系统在不同用户操作和高并发场景下的稳定性和可靠性,同时减少人工测试成本,提高测试效率。

2.测试内容

2.1.功能测试

2.1.1.编写测试用例  

2.1.2.执行测试用例
登录测试
  • (a)界面展示

  • (b)输入正确的账号和密码(如:账号 qiyu,密码 123456
    • 预期结果:成功登录,并跳转至主页。
    • 实际结果:正常
  • (c)输入错误的账号和密码(如:账号 q,密码 1234
    • 预期结果:登录失败,跳出提示
    • 实际结果:正常
  • (d)只输入密码(如:密码 123456
    • 预期结果:登录失败,提示密码不可为空
    • 实际结果:正常
  • (b)只输入账号(如:账号 qiyu
    • 预期结果:登录失败,提示账号不可为空
    • 实际结果:正常
  • (e)不输入账号和密码
    • 预期结果:登录失败,提示账号密码不可为空
    • 实际结果:显示正确
个人中心页测试
  • (a)界面展示

  • (b)测试各各输入框
    • 预期结果:能正常输入修改
    • 实际结果:头像可上传但无法修改,其他正常
帖子编辑页测试
  • (a)界面展示
  • (b)测试板块
    • 预期结果:默认是java和能正常修改
    • 实际结果:正常

  • (c)测试标题框和文字框能否正常输入修改
    • 预期结果:能否正常输入修改
    • 实际结果:修改正常
  • (d)测试能否正常发布
    • 预期结果:发布成功
    • 实际结果
帖子详细页测试
  • (a)界面展示

  • (b)测试菜单栏搜索框
    • 预期结果:正常输入,正常搜索
    • 实际结果:正常输入,但搜索功能无法使用
  • (c)测试菜单栏日间夜间切换按钮
    • 预期结果:可正常切换
    • 实际结果:正常,但会自动切回主页
  • (d)测试菜单栏信息按钮
    • 预期结果:可弹出消息页
    • 实际结果:正常
  • (e)测试个人信息
    • 预期结果:能与登录用户对应
    • 实际结果:对应
  • (f)测试点赞按钮
    • 预期结果:弹窗提示,点赞数量增加
    • 实际结果:成功
  • (g)测试评论区
    • 预期结果:可发送评论
    • 实际结果:正常发送,但在夜间模式输入框输入的文字不可见
  • (h)测试发私信按钮
    • 预期结果:可弹出回复私信页,可正常发送
    • 实际结果:正常
回复私信页测试
  • (a)界面展示
  • (b)测试输入框
    • 预期结果:能正常输入修改
    • 实际结果:正常
  • (c)测试能否正常发送
    • 预期结果:可正常发送
    • 实际结果:正常
首页测试
  • (a)界面展示
  • (b)测试各板块跳转
    • 预期结果:可正常跳转
    • 实际结果:可正常跳转,但缺失部分板块名称
  • (c)测试帖子列表
    • 预期结果:点击进入帖子详细页
    • 实际结果:正常
我的帖子页测试
  • (a)界面展示
  • (b)检查页面信息
    • 预期结果:能与登录用户对应
    • 实际结果:可对应
注册页测试
  • (a)界面展示
  • (b)正常注册测试
    • 预期结果:注册完跳转至登录页
    • 实际结果:正常
  • (c)异常注册测试
    • 预期结果:未输入或两次密码不一致时提示
    • 实际结果:正常

2.2 使用 Selenium 进行 Web 自动化测试(Python)

2.2.1 安装 WebDriverManager 和 Selenium

WebDriverManager 是用于管理 Web 驱动程序的工具,在进行 Selenium 测试时,浏览器需要对应的 WebDriver 进行控制和操作。WebDriverManager 能够自动检测本地浏览器版本并下载匹配的驱动程序(如 ChromeDriver、FirefoxDriver 等),避免手动下载和配置的繁琐过程,提高测试效率和稳定性。


2.2.2 创建测试项目
  1. 在项目中打开 File → Settings,进入设置界面。

  2. 在“Project: 当前项目名”下,检查是否已安装 selenium 和 webdriver-manager 依赖。

  3. 若未安装,可使用以下命令进行安装:

pip install selenium webdriver-manager
公共工具(Utils.py)

测试目标

  • 提供 WebDriver 实例,供各测试脚本调用。

  • 统一管理浏览器驱动,支持截图功能。

测试步骤

  1. 在 Utils.py 中定义 BlogDriver 类,初始化 Edge 浏览器驱动。

  2. 提供 get_driver() 方法,返回 WebDriver 实例。

  3. 提供 screenshot() 方法,支持测试过程中截图。

import datetime
import os
import sys
from webdriver_manager.microsoft import EdgeChromiumDriverManager
from selenium import webdriver
from selenium.webdriver.edge.service import Service
 
 
class Driver:
    driver = None
 
    def __init__(self):
        """初始化WebDriver并启动浏览器"""
        options = webdriver.EdgeOptions()
        options.page_load_strategy = 'eager'
        # options.add_argument('-headless')  # 启动无界面模式
        edge_driver_path = EdgeChromiumDriverManager().install()
        self.driver = webdriver.Edge(service=Service(edge_driver_path), options=options)
 
    def getScreenShot(self):
        """保存当前页面的截图到指定目录"""
        dirname = datetime.datetime.now().strftime('%Y-%m-%d')
        screenshot_dir = os.path.join(os.path.dirname(os.getcwd()), 'images', dirname)
 
        # 如果截图目录不存在,则创建
        if not os.path.exists(screenshot_dir):
            os.makedirs(screenshot_dir)
 
        # 根据方法名和时间戳生成唯一的文件名
        filename = sys._getframe().f_back.f_code.co_name + "-" + datetime.datetime.now().strftime(
            '%Y-%m-%d-%H%M%S') + ".png"
 
        # 保存截图
        screenshot_path = os.path.join(screenshot_dir, filename)
        self.driver.save_screenshot(screenshot_path)
 
 
# 创建BlogDriver实例
BlogDriver = Driver()

登录页自动化测试(Login.py)

测试目标

  • 确保用户登录功能正常,包括不同输入组合的处理逻辑。

测试步骤

  1. 创建 Login.py,引入 Utils.py 及相关依赖。

  2. 定义 Login 类,管理登录页面的测试用例。

  3. 实现以下测试方法:

    • 正确登录测试:使用正确的用户名和密码进行登录,并验证登录成功。

    • 用户名/密码为空测试:测试用户名或密码为空时的登录提示。

    • 用户名/密码错误测试:输入错误的用户名或密码,检查是否拒绝登录。

    • 页面跳转测试:确保登录成功后跳转到主页。

执行方式

  • RunTest.py 中调用 Login 类执行测试。

    import time
    from common.Utils import Driver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.common.alert import Alert
    
    class Login:
        url = ''
        driver = ''
        def __init__(self):
            # 初始化URL和driver,打开登录页面
            self.url = 'http://127.0.0.1:9580/sign-in.html'
            self.driver = Driver.driver
            self.driver.get(self.url)
    
        def _login(self, username, password):
            # 等待提交按钮可点击,输入用户名和密码,并点击登录按钮
            WebDriverWait(self.driver,10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#submit')))
            self.driver.find_element(By.CSS_SELECTOR, '#username').clear()
            self.driver.find_element(By.CSS_SELECTOR, "#password").clear()
            self.driver.find_element(By.CSS_SELECTOR, '#username').send_keys(username)
            self.driver.find_element(By.CSS_SELECTOR, "#password").send_keys(password)
            self.driver.find_element(By.CSS_SELECTOR,'#submit').click()
    
        def _verify_login_success(self):
            """验证用户是否成功登录"""
            try:
                # 等待文章列表标题元素出现来验证是否登录成功
                WebDriverWait(self.driver, 10).until(
                    EC.presence_of_element_located((By.CSS_SELECTOR, '#article_list_board_title')))
            except:
                pass
            # 确认登录后页面中存在文章列表标题
            assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title') is not None
    
        def login_suc_test1(self):
            # 测试用户1的登录
            self._login('qiyu','123456')
            self._verify_login_success()
            Driver.getScreenShot()
            self.driver.back()
    
        def login_suc_test2(self):
            # 测试用户2的登录
            self._login('zhangsan','1234')
            self._verify_login_success()
            self.driver.back()
    
        def check_error_alert(self):
            # 检查错误提示是否出现
            try:
                WebDriverWait(self.driver,5).until(
                    EC.presence_of_element_located((By.CSS_SELECTOR,'body > div.jq-toast-wrap.bottom-right > div'))
                )
            except:
                pass
            # 验证是否有错误提示
            assert self.driver.find_element(By.CSS_SELECTOR,'body > div.jq-toast-wrap.bottom-right > div')
    
        def check_error_appear(self, username, password):
            # 验证错误提示是否在用户名或密码为空时出现
            if username == 'empty':
                try:
                    WebDriverWait(self.driver, 5).until(
                        EC.presence_of_element_located((By.CSS_SELECTOR, '#signInForm > div.mb-3 > div'))
                    )
                except:
                    pass
                # 验证用户名为空时是否出现错误提示
                assert self.driver.find_element(By.CSS_SELECTOR, '#signInForm > div.mb-3 > div')
            if password == 'empty':
                try:
                    WebDriverWait(self.driver, 5).until(
                        EC.presence_of_element_located((By.CSS_SELECTOR, '#signInForm > div.mb-2 > div > div'))
                    )
                except:
                    pass
                # 验证密码为空时是否出现错误提示
                assert self.driver.find_element(By.CSS_SELECTOR, '#signInForm > div.mb-2 > div > div')
    
        def test_login_empty_username_empty_password(self):
            """测试用户名和密码为空时的登录行为"""
            self._login('', '')
            self.check_error_appear('empty','empty')
            self.driver.back()
    
        def test_login_empty_username_valid_password(self):
            """测试用户名为空,密码有效时的登录行为"""
            self._login('', '1234')
            self.check_error_appear('empty','')
            self.driver.back()
    
        def test_login_empty_username_invalid_password(self):
            """测试用户名为空,密码无效时的登录行为"""
            self._login('', '123')
            self.check_error_appear('empty','')
            self.driver.back()
    
        def test_login_invalid_username_empty_password(self):
            """测试用户名无效,密码为空时的登录行为"""
            self._login('123', '')
            self.check_error_appear('','empty')
            self.driver.back()
    
        def test_login_valid_username_empty_password(self):
            """测试用户名有效,密码为空时的登录行为"""
            self._login('zhangsan', '')
            self.check_error_appear('','empty')
            self.driver.back()
    
        def test_login_valid_username_invalid_password(self):
            """测试用户名有效,密码无效时的登录行为"""
            self._login('zhangsan', '123')
            self.check_error_alert()
            self.driver.back()
    
        def test_login_invalid_username_valid_password(self):
            """测试用户名无效,密码有效时的登录行为"""
            self._login('12312', '12334')
            self.check_error_alert()
            self.driver.back()
    
        def test_login_invalid_username_invalid_password(self):
            """测试用户名无效,密码无效时的登录行为"""
            self._login('123', '123')
            self.check_error_alert()
            self.driver.back()
    

注册页自动化测试(Register.py)

测试目标

  • 确保用户注册功能正常,包括不同输入组合的处理逻辑。

测试步骤

  1. 创建 Register.py,引入 Utils.py 及相关依赖。

  2. 定义 Register 类,管理注册页面的测试用例。

  3. 实现以下测试方法:

    • 正确注册测试:填写完整有效信息,并检查注册成功后跳转到登录页。

    • 用户名/密码/昵称为空测试:测试部分字段为空时,系统是否提示错误。

    • 密码不匹配测试:测试密码与确认密码不一致的情况。

    • 未勾选用户协议测试:检查未勾选协议时,是否阻止注册。

执行方式

  • RunTest.py 中调用 Register 类执行测试。

    import time
    import random
    from common.Utils import Driver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    
    class Register:
        driver = ''
        url = ''
        def __init__(self):
            self.url = 'http://127.0.0.1:9580/sign-up.html'
            self.driver = Driver.driver
            self.driver.get(self.url)
    
        def test_valid_inputs_agree_terms(self):
            """测试:所有输入均有效,并且同意条款"""
            random_name = random.randint(100000, 999999)
            random_nickname = random.randint(100000, 999999)
            random_password = random.randint(100000, 999999)
            # 等待输入框加载
            WebDriverWait(self.driver,10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR,'#username'))
            )
            # 填写表单
            self.driver.find_element(By.CSS_SELECTOR, '#username').send_keys(random_name)
            self.driver.find_element(By.CSS_SELECTOR, '#nickname').send_keys(random_nickname)
            self.driver.find_element(By.CSS_SELECTOR, '#password').send_keys(random_password)
            self.driver.find_element(By.CSS_SELECTOR, '#passwordRepeat').send_keys(random_password)
            self.driver.find_element(By.CSS_SELECTOR, '#policy').click()
            self.driver.find_element(By.CSS_SELECTOR,'#submit').click()
            # 等待页面跳转
            WebDriverWait(self.driver,10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR,'body > div > div > div > div:nth-child(1) > div > div.card.card-md > div > h2'))
            )
            # 确认跳转到 "用户登录" 页面
            assert self.driver.find_element(By.CSS_SELECTOR,'body > div > div > div > div:nth-child(1) > div > div.card.card-md > div > h2').text == '用户登录'
            # 登录测试
            self.driver.find_element(By.CSS_SELECTOR,'#username').send_keys(random_name)
            self.driver.find_element(By.CSS_SELECTOR,'#password').send_keys(random_password)
            self.driver.find_element(By.CSS_SELECTOR,'#submit').click()
            try:
                WebDriverWait(self.driver, 10).until(
                    lambda driver: driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-header.d-print-none > div > div > div > h2').text == "首页"
                )
            except:
                pass
            assert self.driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-header.d-print-none > div > div > div > h2').text == '首页'
    
        def test_valid_username_empty_others_disagree_terms(self):
            """测试:用户名有效,其他字段为空,且不同意条款"""
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#username'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#username').send_keys('random_name')
            # 点击提交按钮
            WebDriverWait(self.driver,10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#submit'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#submit').click()
            # 检查错误提示
            WebDriverWait(self.driver, 10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR, '#signUpForm > div > div:nth-child(3) > div'))
            )
            WebDriverWait(self.driver, 10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR, '#signUpForm > div > div:nth-child(4) > div'))
            )
            WebDriverWait(self.driver, 10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR, '#signUpForm > div > div:nth-child(5) > div'))
            )
            assert "is-invalid" in self.driver.find_element(By.ID, "policy").get_attribute("class")
    
        def test_empty_username_valid_nickname_mixed_passwords_disagree_terms(self):
            """测试:用户名为空,昵称有效,密码和确认密码不匹配,且不同意条款"""
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#nickname'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#nickname').send_keys('random_nickname')
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#password'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#password').send_keys('random_password')
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#passwordRepeat'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#passwordRepeat').send_keys('random_passwordRepeat')
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#submit'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#submit').click()
            # 等待错误信息
            WebDriverWait(self.driver, 10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR, '#signUpForm > div > div:nth-child(2) > div'))
            )
            WebDriverWait(self.driver, 10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR, '#signUpForm > div > div:nth-child(5) > div'))
            )
            assert "is-invalid" in self.driver.find_element(By.ID, "policy").get_attribute("class")
    
        def test_empty_username_nickname_valid_password_agree_terms(self):
            """测试:用户名和昵称为空,密码有效,且同意条款"""
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#password'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#password').send_keys('random_password')
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#passwordRepeat'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#passwordRepeat').send_keys('random_password')
            self.driver.find_element(By.CSS_SELECTOR, '#policy').click()
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#submit'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#submit').click()
            # 检查是否出现错误信息
            WebDriverWait(self.driver, 10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR, '#signUpForm > div > div:nth-child(2) > div'))
            )
            WebDriverWait(self.driver, 10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR, '#signUpForm > div > div:nth-child(3) > div'))
            )
            assert "is-valid" in self.driver.find_element(By.ID, "policy").get_attribute("class")
    
        def test_valid_inputs_missing_confirm_password_disagree_terms(self):
            """测试:所有输入有效,但缺少确认密码,且不同意条款"""
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#username'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#username').send_keys('random_name')
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#nickname'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#nickname').send_keys('random_nickname')
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#password'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#password').send_keys('random_password')
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#submit'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#submit').click()
            # 检查是否出现错误信息
            WebDriverWait(self.driver, 10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR, '#signUpForm > div > div:nth-child(5) > div'))
            )
            assert "is-invalid" in self.driver.find_element(By.ID, "policy").get_attribute("class")
    
        def test_valid_username_empty_nickname_password_confirmed_agree_terms(self):
            """测试:用户名有效,昵称为空,密码和确认密码匹配,且同意条款"""
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#username'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#username').send_keys('random_name')
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#password'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#password').send_keys('random_password')
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#passwordRepeat'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#passwordRepeat').send_keys('random_password')
            self.driver.find_element(By.CSS_SELECTOR, '#policy').click()
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#submit'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#submit').click()
            # 检查是否出现错误信息
            WebDriverWait(self.driver, 10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR, '#signUpForm > div > div:nth-child(3) > div'))
            )
            assert "is-valid" in self.driver.find_element(By.ID, "policy").get_attribute("class")
    
        def test_invalid_inputs_disagree_terms(self):
            """测试:所有输入均无效,并且不同意条款"""
            WebDriverWait(self.driver,10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#submit'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#submit').click()
            # 确保所有字段都显示错误
            WebDriverWait(self.driver,10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR, '#signUpForm > div > div:nth-child(2) > div'))
            )
            WebDriverWait(self.driver, 10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR, '#signUpForm > div > div:nth-child(3) > div'))
            )
            WebDriverWait(self.driver, 10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR, '#signUpForm > div > div:nth-child(4) > div'))
            )
            WebDriverWait(self.driver, 10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR, '#signUpForm > div > div:nth-child(5) > div'))
            )
            assert "is-invalid" in self.driver.find_element(By.ID, "policy").get_attribute("class")
    
    

个人主页自动化测试(PersonalHomepage.py)

测试目标

  • 确保个人主页各功能正常,包括修改个人信息、头像、密码等。

测试步骤

  1. 创建 PersonalHomepage.py,引入 Utils.py 及相关依赖。

  2. 定义 PersonalHomepage 类,管理个人主页的测试用例。

  3. 实现以下测试方法:

    • 切换页面测试:测试不同版块的切换功能,确保跳转正确。

    • 修改头像测试:检查头像上传功能是否正常。

    • 修改昵称测试:输入新的昵称并保存,验证是否生效。

    • 修改邮箱/手机号测试:更改邮箱或手机号,并检查更新后的信息。

    • 修改个人简介测试:输入新简介并保存,检查是否成功。

    • 修改密码测试:更改密码并使用新密码重新登录。

执行方式

  • RunTest.py 中调用 PersonalHomepage 类执行测试。

    from common.Utils import Driver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from pywinauto import Application
    from cases import Login
    
    class PersonalHomepage:
        url = ''
        driver = ''
        def __init__(self):
            # 初始化URL和driver,打开首页
            self.url = 'http://127.0.0.1:9580/index.html'
            self.driver = Driver.driver
            self.driver.get(self.url)
            # 等待页面加载完毕并确保头像元素可见
            WebDriverWait(self.driver,10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR,'#index_nav_avatar'))
            )
            # 点击头像,进入个人资料设置页面
            self.driver.find_element(By.CSS_SELECTOR,'#index_nav_avatar').click()
            # 等待个人设置按钮可点击,并点击进入
            WebDriverWait(self.driver,10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR,'#index_user_settings'))
            )
            self.driver.find_element(By.CSS_SELECTOR,'#index_user_settings').click()
    
        def test_switch_section(self):
            """测试不同版块的切换功能"""
            try:
                # 等待“最新回复”板块加载,确保初始状态正确
                WebDriverWait(self.driver, 10).until(
                    lambda driver: driver.find_element(By.CSS_SELECTOR,
                                                       '#bit-forum-content > div.page-body > div > div > div:nth-child(2) > h3').text.strip() == "最新回复"
                )
            except:
                pass  # 忽略异常,继续执行
            # 断言当前版块为“最新回复”
            assert self.driver.find_element(By.CSS_SELECTOR,
                                            '#bit-forum-content > div.page-body > div > div > div:nth-child(2) > h3').text == "最新回复"
            # 切换到首页
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#nav_board_index > a > span.nav-link-title'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#nav_board_index > a > span.nav-link-title').click()
            try:
                # 等待首页加载
                WebDriverWait(self.driver, 10).until(
                    lambda driver: driver.find_element(By.CSS_SELECTOR,
                                                       '#bit-forum-content > div.page-header.d-print-none > div > div > div > h2').text == "首页"
                )
            except:
                pass  # 忽略异常
            # 断言当前版块为“首页”
            assert self.driver.find_element(By.CSS_SELECTOR,
                                            '#bit-forum-content > div.page-header.d-print-none > div > div > div > h2').text == '首页'
            # 切换到“Java”版块
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#topBoardList > li:nth-child(2) > a > span.nav-link-title'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#topBoardList > li:nth-child(2) > a > span.nav-link-title').click()
            try:
                # 等待“Java”版块加载
                WebDriverWait(self.driver, 10).until(
                    lambda driver: driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == "Java"
                )
            except:
                pass
            # 断言当前版块为“Java”
            assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == 'Java'
            # 切换到“C++”版块
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#topBoardList > li:nth-child(3) > a > span.nav-link-title'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#topBoardList > li:nth-child(3) > a > span.nav-link-title').click()
            try:
                # 等待“C++”版块加载
                WebDriverWait(self.driver, 10).until(
                    lambda driver: driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == "C++"
                )
            except:
                pass
            # 断言当前版块为“C++”
            assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == 'C++'
            # 切换到“MySQL”版块
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#topBoardList > li:nth-child(5) > a > span.nav-link-title'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#topBoardList > li:nth-child(5) > a > span.nav-link-title').click()
            try:
                # 等待“MySQL”版块加载
                WebDriverWait(self.driver, 10).until(
                    lambda driver: driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == "MySQL"
                )
            except:
                pass
            # 断言当前版块为“MySQL”
            assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == 'MySQL'
    
        def test_search_input(self):
            """测试搜索框输入功能"""
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR,
                                                'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input'))
            )
            self.driver.find_element(By.CSS_SELECTOR,
                                     'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input').send_keys(
                123)
            # 断言输入的值是否正确
            assert self.driver.find_element(By.CSS_SELECTOR,
                                            "body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input").get_attribute(
                "value") == '123'
    
        def test_toggle_day_night_mode(self):
            """测试日间/夜间模式切换"""
            WebDriverWait(self.driver, 10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR,
                                                  'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-dark > svg'))
            )
            # 断言初始模式为日间模式
            assert self.driver.find_element(By.CSS_SELECTOR, 'body').get_attribute("class") == 'theme-light'
            # 切换到夜间模式
            self.driver.find_element(By.CSS_SELECTOR,
                                     'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-dark > svg').click()
            WebDriverWait(self.driver, 10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR,
                                                  'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-light > svg'))
            )
            # 断言模式已切换为夜间模式
            assert self.driver.find_element(By.CSS_SELECTOR, 'body').get_attribute("class") == 'theme-dark'
            # 切换回日间模式
            self.driver.find_element(By.CSS_SELECTOR,
                                     'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-light > svg').click()
    
        def test_message_button(self):
            """测试消息按钮是否可点击并弹出消息面板"""
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR,
                                            'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > div > a > svg'))
            )
            self.driver.find_element(By.CSS_SELECTOR,
                                     'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > div > a > svg').click()
            assert self.driver.find_element(By.CSS_SELECTOR, '#offcanvasEndLabel')
    
        def test_user_profile(self):
            """测试用户个人信息是否正确显示"""
            self.driver.fullscreen_window()
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#index_nav_nickname'))
            )
            assert self.driver.find_element(By.CSS_SELECTOR, '#index_nav_nickname').text == 'zhangsan'
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#index_nav_name_sub'))
            )
            assert self.driver.find_element(By.CSS_SELECTOR, '#index_nav_name_sub').text == '普通用户'
    
        def test_change_avatar(self):  # 头像修改测试
            # 等待并点击“更换头像”按钮
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR,'#bit-forum-content > div.page-body > div > div > div > div.col.d-flex.flex-column > div > div.row.align-items-center > div:nth-child(2) > a'))
            )
            self.driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-body > div > div > div > div.col.d-flex.flex-column > div > div.row.align-items-center > div:nth-child(2) > a').click()
            # 连接到“打开”窗口
            app = Application().connect(title_re='打开', timeout=1)  # 连接到 "打开" 窗口
            dlg = app.window(title_re="打开")  # 获取窗口
            assert dlg.exist
            dlg.close()
    
        def test_nickname_field(self):  # 昵称栏测试
            random_number = random.randint(100, 999)
            # 等待昵称输入框并进行操作
            WebDriverWait(self.driver,10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR,'#setting_input_nickname'))
            )
            nickname = self.driver.find_element(By.CSS_SELECTOR,'#setting_input_nickname')
            nickname.clear()
            nickname.send_keys(random_number)
            self.driver.find_element(By.CSS_SELECTOR,'#setting_submit_nickname').click()
            # 检查提示信息是否存在
            try:
                WebDriverWait(self.driver,5).until(
                    EC.presence_of_element_located((By.CSS_SELECTOR,'body > div.jq-toast-wrap.bottom-right > div'))
                )
            except:
                pass
            assert self.driver.find_element(By.CSS_SELECTOR,'body > div.jq-toast-wrap.bottom-right > div').text
            # 恢复为默认的“zhangsan”昵称
            nickname.clear()
            nickname.send_keys('zhangsan')
            self.driver.find_element(By.CSS_SELECTOR,'#setting_submit_nickname').click()
    
        def test_email_field(self):  # 邮箱栏测试
            random_number = random.randint(100000, 999999)
            # 等待邮箱输入框并进行操作
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#setting_input_email'))
            )
            email = self.driver.find_element(By.CSS_SELECTOR, '#setting_input_email')
            email.clear()
            email.send_keys(f'{random_number}qq.com')
            self.driver.find_element(By.CSS_SELECTOR, '#setting_submit_email').click()
            # 检查提示信息是否存在
            try:
                WebDriverWait(self.driver, 5).until(
                    EC.presence_of_element_located((By.CSS_SELECTOR, 'body > div.jq-toast-wrap.bottom-right > div'))
                )
            except:
                pass
            assert self.driver.find_element(By.CSS_SELECTOR, 'body > div.jq-toast-wrap.bottom-right > div')
    
        def test_phone_number_field(self):  # 电话号码栏测试
            random_number = random.randint(10000000000, 99999999999)
            # 等待并操作电话号码输入框
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#setting_input_phoneNum'))
            )
            phone = self.driver.find_element(By.CSS_SELECTOR, '#setting_input_phoneNum')
            phone.clear()
            phone.send_keys(random_number)
            self.driver.find_element(By.CSS_SELECTOR, '#setting_submit_phoneNum').click()
            # 检查提示信息是否存在
            try:
                WebDriverWait(self.driver, 5).until(
                    EC.presence_of_element_located((By.CSS_SELECTOR, 'body > div.jq-toast-wrap.bottom-right > div'))
                )
            except:
                pass
            assert self.driver.find_element(By.CSS_SELECTOR, 'body > div.jq-toast-wrap.bottom-right > div')
    
        def test_bio_field(self):  # 个人简介栏测试
            random_number = random.randint(10000000000, 99999999999)
            # 等待并操作个人简介输入框
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#settings_textarea_remark'))
            )
            bio = self.driver.find_element(By.CSS_SELECTOR, '#settings_textarea_remark')
            # 滚动页面使元素可见
            self.driver.execute_script("arguments[0].scrollIntoView();", bio)
            time.sleep(0.5)
            bio.clear()
            bio.send_keys(random_number)
            self.driver.find_element(By.CSS_SELECTOR, '#settings_submit_remark').click()
            # 检查提示信息是否存在
            try:
                WebDriverWait(self.driver, 5).until(
                    EC.presence_of_element_located((By.CSS_SELECTOR, 'body > div.jq-toast-wrap.bottom-right > div'))
                )
            except:
                pass
            assert self.driver.find_element(By.CSS_SELECTOR, 'body > div.jq-toast-wrap.bottom-right > div')
    
        def test_change_password(self):  # 修改密码栏测试
            random_number = random.randint(100, 999)
            print(f'random_password:{random_number}')
            # 等待并操作旧密码、新密码、确认新密码输入框
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#settings_input_oldPassword'))
            )
            oldpassword = self.driver.find_element(By.CSS_SELECTOR, '#settings_input_oldPassword')
            self.driver.execute_script("arguments[0].scrollIntoView();", oldpassword)
            oldpassword.clear()
            oldpassword.send_keys(1234)
            newpassword = self.driver.find_element(By.CSS_SELECTOR, '#settings_input_newPassword')
            self.driver.execute_script("arguments[0].scrollIntoView();", newpassword)
            newpassword.clear()
            newpassword.send_keys(random_number)
            cnewpassword = self.driver.find_element(By.CSS_SELECTOR, '#settings_input_passwordRepeat')
            self.driver.execute_script("arguments[0].scrollIntoView();", cnewpassword)
            cnewpassword.clear()
            cnewpassword.send_keys(random_number)
            element = self.driver.find_element(By.CSS_SELECTOR, '#settings_submit_password')
            self.driver.execute_script("arguments[0].scrollIntoView();", element)
            # 提交修改密码
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#settings_submit_password'))
            )
            time.sleep(0.5)
            element.click()
            # 检查密码修改是否成功
            try:
                WebDriverWait(self.driver, 5).until(
                    EC.presence_of_element_located((By.CSS_SELECTOR, 'body > div > div > div > div:nth-child(1) > div > div.card.card-md > div > h2'))
                )
            except:
                pass
            assert self.driver.find_element(By.CSS_SELECTOR, 'body > div > div > div > div:nth-child(1) > div > div.card.card-md > div > h2')
            # 使用新密码重新登录
            Login.Login()._login('zhangsan',f'{random_number}')
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#index_nav_avatar'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#index_nav_avatar').click()
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#index_user_settings'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#index_user_settings').click()
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#settings_input_oldPassword'))
            )
            oldpassword = self.driver.find_element(By.CSS_SELECTOR, '#settings_input_oldPassword')
            self.driver.execute_script("arguments[0].scrollIntoView();", oldpassword)
            oldpassword.clear()
            oldpassword.send_keys(random_number)
            newpassword = self.driver.find_element(By.CSS_SELECTOR, '#settings_input_newPassword')
            self.driver.execute_script("arguments[0].scrollIntoView();", newpassword)
            newpassword.clear()
            # 恢复密码为初始值
            newpassword.send_keys(1234)
            cnewpassword = self.driver.find_element(By.CSS_SELECTOR, '#settings_input_passwordRepeat')
            self.driver.execute_script("arguments[0].scrollIntoView();", cnewpassword)
            cnewpassword.clear()
            cnewpassword.send_keys(1234)
            element = self.driver.find_element(By.CSS_SELECTOR, '#settings_submit_password')
            self.driver.execute_script("arguments[0].scrollIntoView();", element)
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#settings_submit_password'))
            )
            time.sleep(0.5)
            element.click()
    
    

帖子编辑页自动化测试(Edit.py)

测试目标

  • 确保帖子编辑页功能正常,包括输入标题、内容、板块选择及发布功能。

测试步骤

  1. 创建 Edit.py,引入 Utils.py 及相关依赖。

  2. 定义 Edit 类,管理帖子编辑页面的测试用例。

  3. 实现以下测试方法:

    • 内容框测试:检查帖子内容输入框是否正确加载。

    • 标题输入测试:输入标题并验证输入内容是否正确。

    • 板块选择测试:选择不同板块,并检查选择结果是否正确。

    • 发布测试:点击发布按钮并确保帖子成功发布并跳转到帖子列表页。

执行方式

  • RunTest.py 中调用 Edit 类执行测试。

    import time
    from common.Utils import Driver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.support.ui import Select
    
    class Edit:
        driver = ''
        url = ''
        def __init__(self):
            # 初始化方法,打开指定的URL
            self.url = 'http://127.0.0.1:9580/index.html'
            self.driver = Driver.driver
            self.driver.get(self.url)
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#bit-forum-content > div.page-header.d-print-none > div > div > div.col-auto.ms-auto.d-print-none > div > a.btn.btn-primary.d-none.d-sm-inline-block.article_post'))
            )
            # 点击进入文章发布页面
            self.driver.find_element(By.CSS_SELECTOR, '#bit-forum-content > div.page-header.d-print-none > div > div > div.col-auto.ms-auto.d-print-none > div > a.btn.btn-primary.d-none.d-sm-inline-block.article_post').click()
    
        def Content_Box(self):
            # 内容框测试,检查内容框是否存在
            WebDriverWait(self.driver,10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR,'#edit-article > div.CodeMirror.cm-s-default.CodeMirror-wrap.CodeMirror-empty > div.CodeMirror-scroll > div.CodeMirror-sizer > div > div > div > div.CodeMirror-code > div > pre'))
            )
            # 确认内容框是否已经加载
            self.driver.find_element(By.CSS_SELECTOR,'#edit-article > div.CodeMirror.cm-s-default.CodeMirror-wrap.CodeMirror-empty > div.CodeMirror-scroll > div.CodeMirror-sizer > div > div > div > div.CodeMirror-code > div > pre')
    
        def Title_Bar(self):
            # 标题栏测试,输入并验证标题内容
            WebDriverWait(self.driver,10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR,'#article_post_title'))
            )
            self.driver.find_element(By.CSS_SELECTOR,'#article_post_title').send_keys(1)
            assert self.driver.find_element(By.CSS_SELECTOR,'#article_post_title').get_attribute('value') == "1"
    
        def Plate_Selection(self):
            # 板块选择测试,检查板块选择器中的选项
            WebDriverWait(self.driver,10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR,'#article_post_borad'))
            )
            select = Select(self.driver.find_element(By.CSS_SELECTOR,'#article_post_borad'))
            options = [option.text for option in select.options]
            # 验证板块选项是否正确
            assert 'C++' in options
            assert '前端技术' in options
            assert 'MySQL' in options
            assert '面试宝典' in options
            assert '经验分享' in options
            assert '招聘信息' in options
            assert '福利待遇' in options
            assert '灌水区' in options
            select.select_by_visible_text('C++')
            assert select.first_selected_option.text == 'C++'
    
        def Release(self):
            # 发布测试,点击发布按钮并验证发布反馈
            WebDriverWait(self.driver,10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR,'#article_post_submit'))
            )
            self.driver.execute_script("arguments[0].scrollIntoView();",self.driver.find_element(By.CSS_SELECTOR,'#article_post_submit'))
            time.sleep(0.5)
            self.driver.find_element(By.CSS_SELECTOR,'#article_post_submit').click()
            try:
                WebDriverWait(self.driver, 10).until(
                    EC.presence_of_element_located((By.CSS_SELECTOR, 'body > div.jq-toast-wrap.bottom-right > div'))
                )
            except:
                pass
            # 确认发布后的反馈消息出现
            assert self.driver.find_element(By.CSS_SELECTOR,'body > div.jq-toast-wrap.bottom-right > div')
    
        def test_switch_section(self):
            """测试不同版块的切换功能"""
            try:
                # 等待“最新回复”板块加载,确保初始状态正确
                WebDriverWait(self.driver, 10).until(
                    lambda driver: driver.find_element(By.CSS_SELECTOR,
                                                       '#bit-forum-content > div.page-body > div > div > div:nth-child(2) > h3').text.strip() == "最新回复"
                )
            except:
                pass  # 忽略异常,继续执行
            # 断言当前版块为“最新回复”
            assert self.driver.find_element(By.CSS_SELECTOR,
                                            '#bit-forum-content > div.page-body > div > div > div:nth-child(2) > h3').text == "最新回复"
            # 切换到首页
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#nav_board_index > a > span.nav-link-title'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#nav_board_index > a > span.nav-link-title').click()
            try:
                # 等待首页加载
                WebDriverWait(self.driver, 10).until(
                    lambda driver: driver.find_element(By.CSS_SELECTOR,
                                                       '#bit-forum-content > div.page-header.d-print-none > div > div > div > h2').text == "首页"
                )
            except:
                pass  # 忽略异常
            # 断言当前版块为“首页”
            assert self.driver.find_element(By.CSS_SELECTOR,
                                            '#bit-forum-content > div.page-header.d-print-none > div > div > div > h2').text == '首页'
            # 切换到“Java”版块
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#topBoardList > li:nth-child(2) > a > span.nav-link-title'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#topBoardList > li:nth-child(2) > a > span.nav-link-title').click()
            try:
                # 等待“Java”版块加载
                WebDriverWait(self.driver, 10).until(
                    lambda driver: driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == "Java"
                )
            except:
                pass
            # 断言当前版块为“Java”
            assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == 'Java'
            # 切换到“C++”版块
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#topBoardList > li:nth-child(3) > a > span.nav-link-title'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#topBoardList > li:nth-child(3) > a > span.nav-link-title').click()
            try:
                # 等待“C++”版块加载
                WebDriverWait(self.driver, 10).until(
                    lambda driver: driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == "C++"
                )
            except:
                pass
            # 断言当前版块为“C++”
            assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == 'C++'
            # 切换到“MySQL”版块
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#topBoardList > li:nth-child(5) > a > span.nav-link-title'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#topBoardList > li:nth-child(5) > a > span.nav-link-title').click()
            try:
                # 等待“MySQL”版块加载
                WebDriverWait(self.driver, 10).until(
                    lambda driver: driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == "MySQL"
                )
            except:
                pass
            # 断言当前版块为“MySQL”
            assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == 'MySQL'
    
        def test_search_input(self):
            """测试搜索框输入功能"""
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR,
                                                'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input'))
            )
            self.driver.find_element(By.CSS_SELECTOR,
                                     'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input').send_keys(
                123)
            # 断言输入的值是否正确
            assert self.driver.find_element(By.CSS_SELECTOR,
                                            "body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input").get_attribute(
                "value") == '123'
    
        def test_toggle_day_night_mode(self):
            """测试日间/夜间模式切换"""
            WebDriverWait(self.driver, 10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR,
                                                  'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-dark > svg'))
            )
            # 断言初始模式为日间模式
            assert self.driver.find_element(By.CSS_SELECTOR, 'body').get_attribute("class") == 'theme-light'
            # 切换到夜间模式
            self.driver.find_element(By.CSS_SELECTOR,
                                     'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-dark > svg').click()
            WebDriverWait(self.driver, 10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR,
                                                  'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-light > svg'))
            )
            # 断言模式已切换为夜间模式
            assert self.driver.find_element(By.CSS_SELECTOR, 'body').get_attribute("class") == 'theme-dark'
            # 切换回日间模式
            self.driver.find_element(By.CSS_SELECTOR,
                                     'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-light > svg').click()
    
        def test_message_button(self):
            """测试消息按钮是否可点击并弹出消息面板"""
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR,
                                            'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > div > a > svg'))
            )
            self.driver.find_element(By.CSS_SELECTOR,
                                     'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > div > a > svg').click()
            assert self.driver.find_element(By.CSS_SELECTOR, '#offcanvasEndLabel')
    
        def test_user_profile(self):
            """测试用户个人信息是否正确显示"""
            self.driver.fullscreen_window()
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#index_nav_nickname'))
            )
            assert self.driver.find_element(By.CSS_SELECTOR, '#index_nav_nickname').text == 'zhangsan'
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#index_nav_name_sub'))
            )
            assert self.driver.find_element(By.CSS_SELECTOR, '#index_nav_name_sub').text == '普通用户'
    

帖子详情页自动化测试(Detail.py)

测试目标

  • 确保帖子详情页功能正常,包括查看、评论、点赞等功能。

测试步骤

  1. 创建 Detail.py,引入 Utils.py 及相关依赖。

  2. 定义 Detail 类,管理帖子详情页的测试用例。

  3. 实现以下测试方法:

    • 查看博客测试:进入帖子详情页,确保内容正确显示。

    • 评论测试:输入评论并提交,检查是否成功添加到页面。

    • 点赞测试:点击点赞按钮,确认点赞数增加。

执行方式

  • RunTest.py 中调用 Detail 类执行测试。

    import time
    from common.Utils import Driver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    
    class Detail:
        """页面详情测试类,包含私信、帖子、评论、点赞等功能的测试"""
        driver = ''
        url = ''
        def __init__(self):
            """初始化 WebDriver 并访问指定 URL"""
            self.driver = Driver.driver
            self.url = 'http://127.0.0.1:9580/index.html'
            self.driver.get(self.url)
            # 等待页面关键元素加载
            WebDriverWait(self.driver,10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR,'#artical-items-body > div:nth-child(1) > div > div.col > div.text-truncate > a > strong'))
            )
            # 点击文章进入详情页
            self.driver.find_element(By.CSS_SELECTOR,'#artical-items-body > div:nth-child(1) > div > div.col > div.text-truncate > a > strong').click()
    
        def Private_Message(self):
            """测试私信发送功能"""
            WebDriverWait(self.driver,10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR,'#btn_details_send_message'))
            )
            self.driver.find_element(By.CSS_SELECTOR,'#btn_details_send_message').click()
            # 等待私信弹窗出现
            WebDriverWait(self.driver,10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR,'#index_message_modal > div > div > div.modal-header > h5'))
            )
            assert self.driver.find_element(By.CSS_SELECTOR,'#index_message_modal > div > div > div.modal-header > h5').text == '发送站内信'
            # 发送内容并提交
            self.driver.find_element(By.CSS_SELECTOR,'#index_message_receive_content').send_keys('1')
            self.driver.find_element(By.CSS_SELECTOR,'#btn_index_send_message').click()
            # 等待发送成功的提示
            WebDriverWait(self.driver,10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR,'body > div.jq-toast-wrap.bottom-right > div'))
            )
            # assert '成功' in self.driver.find_element(By.CSS_SELECTOR,'body > div.jq-toast-wrap.bottom-right > div').text
    
        def Post(self):
            """测试帖子内容是否正确加载"""
            WebDriverWait(self.driver,10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR,'#details_article_content > p'))
            )
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#details_article_content_title'))
            )
    
        def Comment(self):
            """测试评论功能"""
            WebDriverWait(self.driver,10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR,'#article_details_reply > div.CodeMirror.cm-s-default.CodeMirror-wrap.CodeMirror-empty > div.CodeMirror-scroll > div.CodeMirror-sizer > div > div > div > div.CodeMirror-code > div > pre'))
            )
            # 滚动到评论框
            self.driver.execute_script("arguments[0].scrollIntoView();", self.driver.find_element(By.CSS_SELECTOR,'#article_details_reply > div.CodeMirror.cm-s-default.CodeMirror-wrap.CodeMirror-empty > div.CodeMirror-scroll > div.CodeMirror-sizer > div > div > div > div.CodeMirror-code > div > pre'))
            time.sleep(0.5) # 等待滚动完成
            self.driver.find_element(By.CSS_SELECTOR,'#details_btn_article_reply > span').click()
            # 确认评论成功提示
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, 'body > div.jq-toast-wrap.bottom-right > div'))
            )
            assert '提示' in self.driver.find_element(By.CSS_SELECTOR, 'body > div.jq-toast-wrap.bottom-right > div').text
    
        def Likes(self):
            """测试点赞功能"""
            WebDriverWait(self.driver,10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR,'#details_article_likeCount'))
            )
            old = int(self.driver.find_element(By.CSS_SELECTOR,'#details_article_likeCount').text)
            # 点击点赞按钮
            self.driver.find_element(By.CSS_SELECTOR,'#details_btn_like_count').click()
            # 等待点赞成功提示
            WebDriverWait(self.driver, 10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR, 'body > div.jq-toast-wrap.bottom-right > div > h2'))
            )
            # 验证点赞数是否增加
            assert old + 1 == int(self.driver.find_element(By.CSS_SELECTOR,'#details_article_likeCount').text)
    
        def test_switch_section(self):
            """测试不同版块的切换功能"""
            try:
                # 等待“最新回复”板块加载,确保初始状态正确
                WebDriverWait(self.driver, 10).until(
                    lambda driver: driver.find_element(By.CSS_SELECTOR, '#bit-forum-content > div.page-body > div > div > div:nth-child(2) > h3').text.strip() == "最新回复"
                )
            except:
                pass# 忽略异常,继续执行
            # 断言当前版块为“最新回复”
            assert self.driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-body > div > div > div:nth-child(2) > h3').text == "最新回复"
            # 切换到首页
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#nav_board_index > a > span.nav-link-title'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#nav_board_index > a > span.nav-link-title').click()
            try:
                # 等待首页加载
                WebDriverWait(self.driver, 10).until(
                    lambda driver: driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-header.d-print-none > div > div > div > h2').text == "首页"
                )
            except:
                pass# 忽略异常
            # 断言当前版块为“首页”
            assert self.driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-header.d-print-none > div > div > div > h2').text == '首页'
            # 切换到“Java”版块
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#topBoardList > li:nth-child(2) > a > span.nav-link-title'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#topBoardList > li:nth-child(2) > a > span.nav-link-title').click()
            try:
                # 等待“Java”版块加载
                WebDriverWait(self.driver, 10).until(
                    lambda driver: driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == "Java"
                )
            except:
                pass
            # 断言当前版块为“Java”
            assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == 'Java'
            # 切换到“C++”版块
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#topBoardList > li:nth-child(3) > a > span.nav-link-title'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#topBoardList > li:nth-child(3) > a > span.nav-link-title').click()
            try:
                # 等待“C++”版块加载
                WebDriverWait(self.driver, 10).until(
                    lambda driver: driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == "C++"
                )
            except:
                pass
            # 断言当前版块为“C++”
            assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == 'C++'
            # 切换到“MySQL”版块
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#topBoardList > li:nth-child(5) > a > span.nav-link-title'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#topBoardList > li:nth-child(5) > a > span.nav-link-title').click()
            try:
                # 等待“MySQL”版块加载
                WebDriverWait(self.driver, 10).until(
                    lambda driver: driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == "MySQL"
                )
            except:
                pass
            # 断言当前版块为“MySQL”
            assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == 'MySQL'
    
        def test_search_input(self):
            """测试搜索框输入功能"""
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input'))
            )
            self.driver.find_element(By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input').send_keys(123)
            # 断言输入的值是否正确
            assert self.driver.find_element(By.CSS_SELECTOR,"body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input").get_attribute("value") == '123'
    
        def test_toggle_day_night_mode(self):
            """测试日间/夜间模式切换"""
            WebDriverWait(self.driver, 10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-dark > svg'))
            )
            # 断言初始模式为日间模式
            assert self.driver.find_element(By.CSS_SELECTOR, 'body').get_attribute("class") == 'theme-light'
            # 切换到夜间模式
            self.driver.find_element(By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-dark > svg').click()
            WebDriverWait(self.driver, 10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-light > svg'))
            )
            # 断言模式已切换为夜间模式
            assert self.driver.find_element(By.CSS_SELECTOR, 'body').get_attribute("class") == 'theme-dark'
            # 切换回日间模式
            self.driver.find_element(By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-light > svg').click()
    
        def test_message_button(self):
            """测试消息按钮是否可点击并弹出消息面板"""
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > div > a > svg'))
            )
            self.driver.find_element(By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > div > a > svg').click()
            assert self.driver.find_element(By.CSS_SELECTOR, '#offcanvasEndLabel')
    
        def test_user_profile(self):
            """测试用户个人信息是否正确显示"""
            self.driver.fullscreen_window()
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#index_nav_nickname'))
            )
            assert self.driver.find_element(By.CSS_SELECTOR, '#index_nav_nickname').text == 'zhangsan'
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#index_nav_name_sub'))
            )
            assert self.driver.find_element(By.CSS_SELECTOR, '#index_nav_name_sub').text == '普通用户'
    

首页自动化测试(HomePage.py)

测试目标

  • 确保首页的基本交互功能正常,包括查看帖子列表、切换主题、搜索等。

测试步骤

  1. 创建 HomePage.py,引入 Utils.py 及相关依赖。

  2. 定义 HomePage 类,管理首页的测试用例。

  3. 实现以下测试方法:

    • 博客列表测试:检查帖子列表是否正确加载。

    • 搜索测试:输入关键词并验证搜索结果是否符合预期。

    • 日夜模式切换测试:切换日间/夜间模式,并验证切换效果。

执行方式

  • RunTest.py 中调用 HomePage 类执行测试。

    import time
    from common.Utils import Driver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    
    class HomePage:
        driver = ''
        url = ''
        def __init__(self):
            # 初始化URL和driver
            self.url = 'http://127.0.0.1:9580/index.html'
            self.driver = Driver.driver
            self.driver.get(self.url)
    
        def Button(self):
            # 等待"发新贴"按钮可点击,并点击它
            WebDriverWait(self.driver,10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR,'#bit-forum-content > div.page-header.d-print-none > div > div > div.col-auto.ms-auto.d-print-none > div > a.btn.btn-primary.d-none.d-sm-inline-block.article_post'))
            )
            self.driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-header.d-print-none > div > div > div.col-auto.ms-auto.d-print-none > div > a.btn.btn-primary.d-none.d-sm-inline-block.article_post').click()
            # 验证页面是否跳转到“发新贴”
            WebDriverWait(self.driver, 10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR,'#bit-forum-content > div.page-header.d-print-none > div > div > div > h2'))
            )
            assert self.driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-header.d-print-none > div > div > div > h2').text == '发新贴'
    
        def List(self):
            # 等待第一个帖子可点击,并点击它
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#artical-items-body > div:nth-child(1) > div > div.col > div.text-truncate > a > strong'))
            )
            self.driver.find_element(By.CSS_SELECTOR,'#artical-items-body > div:nth-child(1) > div > div.col > div.text-truncate > a > strong').click()
            # 验证页面是否跳转到“最新回复”区域
            WebDriverWait(self.driver, 10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR,'#bit-forum-content > div.page-body > div > div > div:nth-child(2) > h3'))
            )
            assert self.driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-body > div > div > div:nth-child(2) > h3').text == '最新回复'
    
        def test_switch_section(self):
            """测试不同版块的切换功能"""
            try:
                # 等待“最新回复”板块加载,确保初始状态正确
                WebDriverWait(self.driver, 10).until(
                    lambda driver: driver.find_element(By.CSS_SELECTOR,
                                                       '#bit-forum-content > div.page-body > div > div > div:nth-child(2) > h3').text.strip() == "最新回复"
                )
            except:
                pass  # 忽略异常,继续执行
            # 断言当前版块为“最新回复”
            assert self.driver.find_element(By.CSS_SELECTOR,
                                            '#bit-forum-content > div.page-body > div > div > div:nth-child(2) > h3').text == "最新回复"
            # 切换到首页
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#nav_board_index > a > span.nav-link-title'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#nav_board_index > a > span.nav-link-title').click()
            try:
                # 等待首页加载
                WebDriverWait(self.driver, 10).until(
                    lambda driver: driver.find_element(By.CSS_SELECTOR,
                                                       '#bit-forum-content > div.page-header.d-print-none > div > div > div > h2').text == "首页"
                )
            except:
                pass  # 忽略异常
            # 断言当前版块为“首页”
            assert self.driver.find_element(By.CSS_SELECTOR,
                                            '#bit-forum-content > div.page-header.d-print-none > div > div > div > h2').text == '首页'
            # 切换到“Java”版块
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#topBoardList > li:nth-child(2) > a > span.nav-link-title'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#topBoardList > li:nth-child(2) > a > span.nav-link-title').click()
            try:
                # 等待“Java”版块加载
                WebDriverWait(self.driver, 10).until(
                    lambda driver: driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == "Java"
                )
            except:
                pass
            # 断言当前版块为“Java”
            assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == 'Java'
            # 切换到“C++”版块
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#topBoardList > li:nth-child(3) > a > span.nav-link-title'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#topBoardList > li:nth-child(3) > a > span.nav-link-title').click()
            try:
                # 等待“C++”版块加载
                WebDriverWait(self.driver, 10).until(
                    lambda driver: driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == "C++"
                )
            except:
                pass
            # 断言当前版块为“C++”
            assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == 'C++'
            # 切换到“MySQL”版块
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#topBoardList > li:nth-child(5) > a > span.nav-link-title'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#topBoardList > li:nth-child(5) > a > span.nav-link-title').click()
            try:
                # 等待“MySQL”版块加载
                WebDriverWait(self.driver, 10).until(
                    lambda driver: driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == "MySQL"
                )
            except:
                pass
            # 断言当前版块为“MySQL”
            assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == 'MySQL'
    
        def test_search_input(self):
            """测试搜索框输入功能"""
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR,
                                                'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input'))
            )
            self.driver.find_element(By.CSS_SELECTOR,
                                     'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input').send_keys(
                123)
            # 断言输入的值是否正确
            assert self.driver.find_element(By.CSS_SELECTOR,
                                            "body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input").get_attribute(
                "value") == '123'
    
        def test_toggle_day_night_mode(self):
            """测试日间/夜间模式切换"""
            WebDriverWait(self.driver, 10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR,
                                                  'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-dark > svg'))
            )
            # 断言初始模式为日间模式
            assert self.driver.find_element(By.CSS_SELECTOR, 'body').get_attribute("class") == 'theme-light'
            # 切换到夜间模式
            self.driver.find_element(By.CSS_SELECTOR,
                                     'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-dark > svg').click()
            WebDriverWait(self.driver, 10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR,
                                                  'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-light > svg'))
            )
            # 断言模式已切换为夜间模式
            assert self.driver.find_element(By.CSS_SELECTOR, 'body').get_attribute("class") == 'theme-dark'
            # 切换回日间模式
            self.driver.find_element(By.CSS_SELECTOR,
                                     'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-light > svg').click()
    
        def test_message_button(self):
            """测试消息按钮是否可点击并弹出消息面板"""
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR,
                                            'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > div > a > svg'))
            )
            self.driver.find_element(By.CSS_SELECTOR,
                                     'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > div > a > svg').click()
            assert self.driver.find_element(By.CSS_SELECTOR, '#offcanvasEndLabel')
    
        def test_user_profile(self):
            """测试用户个人信息是否正确显示"""
            self.driver.fullscreen_window()
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#index_nav_nickname'))
            )
            assert self.driver.find_element(By.CSS_SELECTOR, '#index_nav_nickname').text == 'zhangsan'
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#index_nav_name_sub'))
            )
            assert self.driver.find_element(By.CSS_SELECTOR, '#index_nav_name_sub').text == '普通用户'
    

私信功能自动化测试(PrivateMessage.py)

测试目标

  • 确保私信功能正常,包括查看和发送私信。

测试步骤

  1. 创建 PrivateMessage.py,引入 Utils.py 及相关依赖。

  2. 定义 PrivateMessage 类,管理私信的测试用例。

  3. 实现以下测试方法:

    • 查看私信测试:进入私信列表并点击某条私信,检查内容是否正确显示。

    • 发送私信测试:输入内容并发送,确保私信成功发送。

执行方式

  • RunTest.py 中调用 PrivateMessage 类执行测试。

    import time
    from common.Utils import Driver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    
    class PrivateMessage:
        url = ''
        driver = ''
        def __init__(self):
            self.driver = Driver.driver
            self.url = 'http://127.0.0.1:9580/index.html'
            self.driver.get(self.url)
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > div > a > svg'))
            )
            self.driver.find_element(By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > div > a > svg').click()
            assert self.driver.find_element(By.CSS_SELECTOR, '#offcanvasEndLabel')
    
        def reply(self):
            # 等待并点击私信列表中的第一条消息
            WebDriverWait(self.driver,10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR,'#index_div_message_list > div:nth-child(1) > div > div.col.text-truncate > a'))
            )
            self.driver.find_element(By.CSS_SELECTOR,'#index_div_message_list > div:nth-child(1) > div > div.col.text-truncate > a').click()
            # 等待 "取消回复" 按钮出现并点击
            WebDriverWait(self.driver, 10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR, '#index_message_reply_cancel'))
            )
            self.driver.find_element(By.CSS_SELECTOR,'#index_message_reply_cancel').click()
            # 再次点击同一条私信,重新进入回复界面
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#index_div_message_list > div:nth-child(1) > div > div.col.text-truncate > a'))
            )
            self.driver.find_element(By.CSS_SELECTOR,'#index_div_message_list > div:nth-child(1) > div > div.col.text-truncate > a').click()
            # 等待 "回复" 按钮出现并点击
            WebDriverWait(self.driver, 10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR, '#btn_index_message_reply'))
            )
            self.driver.find_element(By.CSS_SELECTOR,'#btn_index_message_reply').click()
            # 等待回复输入框并输入消息
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#index_message_reply_receive_content'))
            )
            self.driver.find_element(By.CSS_SELECTOR,'#index_message_reply_receive_content').send_keys(123)
            # 等待 "发送回复" 按钮出现并点击
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#btn_index_send_message_reply'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#btn_index_send_message_reply').click()
            # 等待并检查是否有成功提示
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, 'body > div.jq-toast-wrap.bottom-right > div'))
            )
            assert '成功' in self.driver.find_element(By.CSS_SELECTOR, 'body > div.jq-toast-wrap.bottom-right > div').text

我的帖子自动化测试(MyPost.py)

测试目标

  • 确保“我的帖子”页面功能正常,包括查看、管理已发布的帖子。

测试步骤

  1. 创建 MyPost.py,引入 Utils.py 及相关依赖。

  2. 定义 MyPost 类,管理“我的帖子”页面的测试用例。

  3. 实现以下测试方法:

    • 查看已发布帖子:进入“我的帖子”页面,检查列表是否正确显示。

    • 编辑帖子测试:点击某个帖子进行编辑,检查是否能正常修改并保存。

    • 删除帖子测试:删除某个帖子,并检查列表是否正确更新。

执行方式

  • RunTest.py 中调用 MyPost 类执行测试。

    import time
    from common.Utils import Driver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    
    class MyPost:
        driver = ''
        url = ''
        def __init__(self):
            # 初始化URL和driver,打开用户首页
            self.url = 'http://127.0.0.1:9580/index.html'
            self.driver = Driver.driver
            self.driver.get(self.url)
            # 等待页面加载完毕,点击头像进入用户资料页面
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#index_nav_avatar'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#index_nav_avatar').click()
            # 等待用户资料链接可点击,进入用户资料页面
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR,'#index_user_profile'))
            )
            self.driver.find_element(By.CSS_SELECTOR,'#index_user_profile').click()
    
        def Name(self):
            # 等待用户昵称加载完成,并验证昵称是否为 'zhangsan'
            WebDriverWait(self.driver,10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR,'#profile_nickname'))
            )
            # 验证昵称是否正确
            assert self.driver.find_element(By.CSS_SELECTOR,'#profile_nickname').text == 'zhangsan'
    
        def Post(self):
            # 等待第一个帖子可点击
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#profile_article_body > li:nth-child(1) > div.card.timeline-event-card > div > div > div > div > div.text-truncate > a > strong'))
            )
            self.driver.find_element(By.CSS_SELECTOR,'#profile_article_body > li:nth-child(1) > div.card.timeline-event-card > div > div > div > div > div.text-truncate > a > strong').click()
            try:
                # 等待文章编辑按钮出现,若出现则表示该帖子可以编辑
                WebDriverWait(self.driver,10).until(
                    EC.presence_of_element_located((By.CSS_SELECTOR,'#details_artile_edit'))
                )
            except:
                pass
            # 验证是否可以编辑帖子
            assert self.driver.find_element(By.CSS_SELECTOR,'#details_artile_edit')
    
        def test_switch_section(self):
            """测试不同版块的切换功能"""
            try:
                # 等待“最新回复”板块加载,确保初始状态正确
                WebDriverWait(self.driver, 10).until(
                    lambda driver: driver.find_element(By.CSS_SELECTOR,
                                                       '#bit-forum-content > div.page-body > div > div > div:nth-child(2) > h3').text.strip() == "最新回复"
                )
            except:
                pass  # 忽略异常,继续执行
            # 断言当前版块为“最新回复”
            assert self.driver.find_element(By.CSS_SELECTOR,
                                            '#bit-forum-content > div.page-body > div > div > div:nth-child(2) > h3').text == "最新回复"
            # 切换到首页
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#nav_board_index > a > span.nav-link-title'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#nav_board_index > a > span.nav-link-title').click()
            try:
                # 等待首页加载
                WebDriverWait(self.driver, 10).until(
                    lambda driver: driver.find_element(By.CSS_SELECTOR,
                                                       '#bit-forum-content > div.page-header.d-print-none > div > div > div > h2').text == "首页"
                )
            except:
                pass  # 忽略异常
            # 断言当前版块为“首页”
            assert self.driver.find_element(By.CSS_SELECTOR,
                                            '#bit-forum-content > div.page-header.d-print-none > div > div > div > h2').text == '首页'
            # 切换到“Java”版块
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#topBoardList > li:nth-child(2) > a > span.nav-link-title'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#topBoardList > li:nth-child(2) > a > span.nav-link-title').click()
            try:
                # 等待“Java”版块加载
                WebDriverWait(self.driver, 10).until(
                    lambda driver: driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == "Java"
                )
            except:
                pass
            # 断言当前版块为“Java”
            assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == 'Java'
            # 切换到“C++”版块
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#topBoardList > li:nth-child(3) > a > span.nav-link-title'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#topBoardList > li:nth-child(3) > a > span.nav-link-title').click()
            try:
                # 等待“C++”版块加载
                WebDriverWait(self.driver, 10).until(
                    lambda driver: driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == "C++"
                )
            except:
                pass
            # 断言当前版块为“C++”
            assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == 'C++'
            # 切换到“MySQL”版块
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#topBoardList > li:nth-child(5) > a > span.nav-link-title'))
            )
            self.driver.find_element(By.CSS_SELECTOR, '#topBoardList > li:nth-child(5) > a > span.nav-link-title').click()
            try:
                # 等待“MySQL”版块加载
                WebDriverWait(self.driver, 10).until(
                    lambda driver: driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == "MySQL"
                )
            except:
                pass
            # 断言当前版块为“MySQL”
            assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == 'MySQL'
    
        def test_search_input(self):
            """测试搜索框输入功能"""
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR,
                                                'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input'))
            )
            self.driver.find_element(By.CSS_SELECTOR,
                                     'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input').send_keys(
                123)
            # 断言输入的值是否正确
            assert self.driver.find_element(By.CSS_SELECTOR,
                                            "body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input").get_attribute(
                "value") == '123'
    
        def test_toggle_day_night_mode(self):
            """测试日间/夜间模式切换"""
            WebDriverWait(self.driver, 10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR,
                                                  'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-dark > svg'))
            )
            # 断言初始模式为日间模式
            assert self.driver.find_element(By.CSS_SELECTOR, 'body').get_attribute("class") == 'theme-light'
            # 切换到夜间模式
            self.driver.find_element(By.CSS_SELECTOR,
                                     'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-dark > svg').click()
            WebDriverWait(self.driver, 10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR,
                                                  'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-light > svg'))
            )
            # 断言模式已切换为夜间模式
            assert self.driver.find_element(By.CSS_SELECTOR, 'body').get_attribute("class") == 'theme-dark'
            # 切换回日间模式
            self.driver.find_element(By.CSS_SELECTOR,
                                     'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-light > svg').click()
    
        def test_message_button(self):
            """测试消息按钮是否可点击并弹出消息面板"""
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR,
                                            'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > div > a > svg'))
            )
            self.driver.find_element(By.CSS_SELECTOR,
                                     'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > div > a > svg').click()
            assert self.driver.find_element(By.CSS_SELECTOR, '#offcanvasEndLabel')
    
        def test_user_profile(self):
            """测试用户个人信息是否正确显示"""
            self.driver.fullscreen_window()
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#index_nav_nickname'))
            )
            assert self.driver.find_element(By.CSS_SELECTOR, '#index_nav_nickname').text == 'zhangsan'
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#index_nav_name_sub'))
            )
            assert self.driver.find_element(By.CSS_SELECTOR, '#index_nav_name_sub').text == '普通用户'
    

运行所有测试(RunTest.py)

测试目标

  • 依次执行所有测试,并确保最终关闭 WebDriver。

测试步骤

  1. 创建 RunTest.py,引入 Utils.py 及所有测试文件。

  2. 依次调用各个测试类的测试方法。

  3. 统一管理 WebDriver 的初始化和退出。

执行方式

  • 直接运行 RunTest.py,所有测试会自动执行。

import time
from common.Utils import Driver
from cases import Login,PersonalHomepage,Edit,Detail,PrivateMessage,HomePage,MyPost,Register

# 运行登录相关的测试
def run_Login_tests():
    """执行所有登录相关的测试"""
    login = Login.Login()  # 只实例化一次,避免重复创建对象
    login.login_suc_test1()
    login.login_suc_test2()
    login.test_login_empty_username_empty_password()
    login.test_login_empty_username_valid_password()
    login.test_login_empty_username_invalid_password()
    login.test_login_invalid_username_empty_password()
    login.test_login_valid_username_empty_password()
    login.test_login_valid_username_invalid_password()
    login.test_login_invalid_username_valid_password()
    login.test_login_invalid_username_invalid_password()

# 运行个人主页相关的测试
def run_PersonalHomepage_tests():
    """执行所有个人主页相关的测试"""
    personal_home = PersonalHomepage.PersonalHomepage()
    personal_home.test_switch_section()
    personal_home.test_search_input()
    personal_home.test_toggle_day_night_mode()
    personal_home.test_message_button()
    personal_home.test_user_profile()
    personal_home.test_change_avatar()
    personal_home.test_nickname_field()
    personal_home.test_email_field()
    personal_home.test_phone_number_field()
    personal_home.test_bio_field()
    personal_home.test_change_password()

# 运行帖子编辑相关的测试
def run_Edit_tests():
    """执行所有帖子编辑相关的测试"""
    edit = Edit.Edit()
    edit.Content_Box()
    edit.Title_Bar()
    edit.Plate_Selection()
    edit.Release()
    edit.test_switch_section()
    edit.test_search_input()
    edit.test_toggle_day_night_mode()
    edit.test_message_button()
    edit.test_user_profile()

# 运行帖子详情相关的测试
def run_Detail_tests():
    """执行所有帖子详情页面相关的测试"""
    detail = Detail.Detail()
    detail.Private_Message()
    detail.Post()
    detail.Comment()
    detail.Likes()
    detail.test_switch_section()
    detail.test_search_input()
    detail.test_toggle_day_night_mode()
    detail.test_message_button()
    detail.test_user_profile()

# 运行私信功能的测试
def run_PrivateMessage_tests():
    """执行私信功能的测试"""
    private_msg = PrivateMessage.PrivateMessage()
    private_msg.reply()

# 运行首页相关的测试
def run_HomePage_tests():
    """执行所有首页相关的测试"""
    home = HomePage.HomePage()
    home.Button()
    home.List()
    home.test_switch_section()
    home.test_search_input()
    home.test_toggle_day_night_mode()
    home.test_message_button()
    home.test_user_profile()

# 运行“我的帖子”相关的测试
def run_MyPost_test():
    """执行所有‘我的帖子’相关的测试"""
    my_post = MyPost.MyPost()
    my_post.Name()
    my_post.Post()
    my_post.test_switch_section()
    my_post.test_search_input()
    my_post.test_toggle_day_night_mode()
    my_post.test_message_button()
    my_post.test_user_profile()

# 运行注册功能的测试
def run_Register_test():
    """执行所有注册功能的测试"""
    register = Register.Register()
    register.test_valid_inputs_agree_terms()
    register.test_valid_username_empty_others_disagree_terms()
    register.test_empty_username_valid_nickname_mixed_passwords_disagree_terms()
    register.test_empty_username_nickname_valid_password_agree_terms()
    register.test_valid_inputs_missing_confirm_password_disagree_terms()
    register.test_valid_username_empty_nickname_password_confirmed_agree_terms()
    register.test_invalid_inputs_disagree_terms()

# 运行所有测试
def run_all_tests():
    """依次执行所有的测试,并在结束后关闭 WebDriver"""
    try:
        run_Login_tests()
        run_PersonalHomepage_tests()
        run_Edit_tests()
        run_Detail_tests()
        run_PrivateMessage_tests()
        run_HomePage_tests()
        run_MyPost_test()
        run_Register_test()
    except Exception as e:
        print(f"错误发生: {e}")  # 捕获异常,避免测试中断
    finally:
        Driver.driver.quit()  # 测试完成后关闭 WebDriver

# 主函数
if __name__ == '__main__':
    run_all_tests()
可优化部分
  • 菜单反复调用测试,可以专门写一个对菜单功能测试的函数
  • 注释没有统一格式
  • 好多地方截图没补上去

前面几个像登录测试注册那种选择多的是用 allpairs搞定的

3.各函数作用总览

Utils.py
  • __init__(self): 初始化 WebDriver。

  • getScreenShot(self): 截取当前页面截图并保存。


Login.py
  • __init__(self): 初始化 WebDriver 并打开登录页面。

  • _login(self, username, password): 输入用户名和密码,执行登录操作。

  • _verify_login_success(self): 验证用户是否成功登录。

  • login_suc_test1(self): 测试正确的用户名和密码能否成功登录。

  • login_suc_test2(self): 测试另一个正确的用户名和密码登录是否成功。

  • test_login_empty_username_empty_password(self): 测试用户名和密码都为空的情况。

  • test_login_valid_username_empty_password(self): 测试用户名正确但密码为空的情况。

  • test_login_invalid_username_valid_password(self): 测试用户名错误但密码正确的情况。


Register.py
  • __init__(self): 初始化 WebDriver 并打开注册页面。

  • test_valid_inputs_agree_terms(self): 测试所有输入正确且同意条款的情况。

  • test_valid_username_empty_others_disagree_terms(self): 测试仅填写用户名,其他字段为空且不同意条款的情况。

  • test_empty_username_valid_nickname_mixed_passwords_disagree_terms(self): 测试用户名为空、昵称有效但密码不匹配的情况。

  • test_empty_username_nickname_valid_password_agree_terms(self): 测试用户名和昵称为空,密码正确且同意条款的情况。


Edit.py
  • __init__(self): 初始化 WebDriver 并进入编辑页面。

  • Content_Box(self): 检查博客内容输入框是否正确加载。

  • Title_Bar(self): 输入标题并验证输入是否正确。

  • Plate_Selection(self): 选择不同的板块,并检查选择结果是否正确。

  • Release(self): 点击发布按钮,确保博客成功发布。

  • test_switch_section(self): 测试博客发布后页面是否能正确跳转到博客列表。


Detail.py
  • __init__(self): 初始化 WebDriver 并打开博客详情页。

  • Private_Message(self): 测试私信功能,确保发送私信成功。

  • Post(self): 测试博客内容是否正确显示。

  • Comment(self): 测试用户能否成功发表评论。

  • Likes(self): 测试点赞按钮是否正常工作。


PersonalHomepage.py
  • __init__(self): 初始化 WebDriver 并打开个人主页。

  • test_change_avatar(self): 测试头像修改功能。

  • test_nickname_field(self): 测试修改昵称并检查是否保存成功。

  • test_email_field(self): 测试修改邮箱并验证更新后的信息。

  • test_phone_number_field(self): 测试修改手机号功能。

  • test_bio_field(self): 测试个人简介的编辑与保存功能。

  • test_change_password(self): 测试修改密码,并使用新密码重新登录。


PrivateMessage.py
  • __init__(self): 初始化 WebDriver 并进入私信页面。

  • reply(self): 测试私信回复功能,确保发送成功。


HomePage.py
  • __init__(self): 初始化 WebDriver 并打开首页。

  • Button(self): 测试首页“发新贴”按钮是否能正常跳转到编辑页面。

  • List(self): 测试博客列表是否正确加载,并可点击查看详情。

  • test_search_input(self): 测试搜索框输入内容,并检查搜索结果。

  • test_toggle_day_night_mode(self): 测试日间/夜间模式的切换功能。


MyPost.py
  • __init__(self): 初始化 WebDriver 并进入“我的帖子”页面。

  • Name(self): 检查用户名是否正确显示。

  • Post(self): 测试点击某个帖子,确保页面跳转正常。


Test.py
  • run_all_tests(): 运行所有测试用例,确保所有功能正常执行。

4.测试环境与执行方式

运行环境
  • Python 版本:3.13

  • 依赖库:selenium

  • 浏览器:Microsoft Edge   版本 134.0.3124.68 (正式版本) (64 位)

  • WebDriver:msedgedriver 需正确配置

运行方式
  1. 安装 selenium 依赖:

    pip install selenium
  2. 确保 msedgedriver 已正确安装。

  3. 运行 RunCases.py 以执行完整的测试流程:

    python RunCases.py
结果验证
  • 所有测试案例执行完成后,测试日志将会记录各个测试步骤的执行结果。

  • 关键页面截图将在 images/ 目录中保存,以供参考。

  • 若有测试失败,请参考日志进行问题排查,并根据错误信息调整代码或系统设置。

 5.自动化框架特点与亮点

特点

该自动化测试框架结合了 Selenium WebDriver自定义测试模块,能够高效地验证论坛的各项功能。测试用例覆盖了从 用户注册、登录、发布帖子、浏览帖子、私信交互、个人信息管理页面跳转 等多个关键场景。

所有测试用例都封装为独立的函数,目标明确,执行步骤清晰,便于维护和扩展。自动化测试可以反复执行,提高测试覆盖率的同时,也减少了人工干预,提高测试效率。

此外,该框架还利用 Selenium WebDriver 的等待机制,确保页面元素完全加载后再执行操作,减少因页面加载缓慢导致的测试失败。同时,截图功能 使得测试过程可追踪,异常情况可视化,便于快速定位问题。


亮点

1. 统一的 WebDriver 管理
  • 采用 Driver 类 统一管理 WebDriver 实例,避免每个测试用例重复创建 WebDriver,减少资源浪费,提高执行效率。

  • 通过 单例模式 复用 WebDriver,在多个测试用例间共享浏览器会话,减少重复初始化的开销。

2. 功能清晰的测试用例
  • 每个测试用例都封装成独立的函数,清晰定义测试目标验证条件,增强了代码的可读性和可维护性。

  • 测试覆盖了帖子网站的核心功能,包括:

    • 用户注册与登录:模拟不同用户的登录情况,验证账号验证逻辑。

    • 帖子管理:测试帖子的发布、编辑、删除等功能,确保用户可以正常管理文章。

    • 交互功能:测试评论、私信、点赞等用户互动功能,确保社交体验顺畅。

3. 高效的等待机制
  • 结合 显式等待 (WebDriverWait)隐式等待,有效解决页面加载速度和测试执行速度不一致的问题。

  • 避免因为页面元素未完全渲染而导致的 NoSuchElementExceptionElementNotInteractableException,提高测试稳定性和可靠性。

4. 自动截图功能
  • 每个测试用例执行时,自动截图关键操作,便于在测试失败时进行问题追踪和回溯。

  • 结合 日志记录功能,在测试失败时保存错误信息,帮助开发人员快速定位和修复问题。

5. 自动化的重复执行
  • 该框架可以轻松地多次执行同一组测试,适用于回归测试稳定性测试,确保系统在不同时间段或高并发情况下依然表现正常。

  • 结合 定时任务 (cron jobs) 或 CI/CD 流水线,可实现每日自动化回归测试,保证系统功能始终可用。

6. 页面元素检查与交互验证
  • 通过 WebDriver 的 presence_of_element_located()visibility_of_element_located() 方法,确保所有关键元素在交互前正确加载

  • 检测页面上的按钮、表单、文本框等控件是否可点击、可输入、可提交,防止界面交互异常。

 6.性能测试

使用 Apache JMeter论坛系统 进行性能测试,模拟不同用户操作下的系统响应情况,确保系统能够在高并发访问下稳定运行。

测试目标
  • 评估 用户登录、浏览帖子、查看详情、发表帖子 等关键功能的响应时间和吞吐量

  • 通过 并发请求模拟大量用户访问,检查系统的稳定性

  • 记录并分析 响应时间、线程活动情况、事务处理速度,优化系统性能

测试步骤
  1. HTTP 请求默认值设置:定义论坛系统的基本 URL,简化后续请求配置

  2. HTTP 头信息管理器:设置请求头,模拟真实浏览器访问

  3. 自定义变量:定义通用变量,便于动态参数传递

  4. 账号密码 CSV 数据管理:使用 CSV 文件导入用户信息,模拟多个用户登录

  5. HTTP Cookie 管理器:存储会话信息,确保用户身份在请求间保持一致

  6. 执行测试事务

    • 用户登录:模拟用户输入账号密码并登录

    • 用户信息:获取用户的个人资料

    • 列表页:访问帖子列表,测试加载速度

    • 详情页:查看特定帖子内容,测试响应时间

    • 添加帖子:模拟用户发布新帖,验证提交效率

  7. 结果分析

    • 查看结果树:检查每个请求的详细响应数据

    • 聚合报告:统计请求数量、平均响应时间、吞吐量等指标

    • JMeter 监控插件

      • Active Threads Over Time:观察系统在不同时间点的并发用户数

      • Response Times Over Time:分析不同时间点的服务器响应时间

      • Transactions per Second:统计系统每秒钟处理的事务数

 

列表那异常爆表了啊

应该是那一页数据太多的问题

性能测试还在学,这就测的大概,看个乐 

8.完整测试代码连接 

GitHub - bbppooii/Automated-testing-of-forum-system

bbppooi/论坛系统自动化测试

9.补充

补了个错误总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值