├── .idea ├── .gitignore ├── inspectionProfiles │ └── profiles_settings.xml ├── misc.xml ├── modules.xml └── 课堂派web.iml ├── README.md ├── common └── base_page.py ├── config └── config.py ├── conftest.py ├── data ├── course_data.py ├── homework_data.py ├── login_data.py └── send_message_data.py ├── files ├── png图片.png ├── py代码.py ├── txt文档.txt ├── xlsx文件.xlsx └── 压缩包.rar ├── pages ├── class_page.py ├── homework_page.py ├── login_page.py ├── main_page.py └── students_page.py ├── pytest.ini ├── reports ├── assets │ └── style.css ├── test_all │ ├── 0211c339-c64f-42e8-8307-0f9f0814133f-result.json │ ├── 10a69e1c-99d2-48d4-ae3a-38620b1d9e42-container.json │ ├── 1540e390-1fab-4ff5-8d26-c043180e994a-container.json │ ├── 195e7880-743b-4e9d-82cb-4d86ef52ee4b-container.json │ ├── 1cc0f639-8e8c-46fa-b0ca-eccbb88d481a-container.json │ ├── 2979e93a-2452-458e-886d-dcd6dd045e9a-result.json │ ├── 2c0512bc-f100-4275-9e03-5312c8699682-result.json │ ├── 30146b79-9c47-4dff-bc14-e52af2f7435c-container.json │ ├── 3fb542d1-74a1-475a-8aac-70bcc09542ce-container.json │ ├── 41576d93-caea-404c-9a92-1f02489994df-container.json │ ├── 4429863e-9cc5-4f67-a367-af537333daf3-container.json │ ├── 451470ca-99d8-4a80-b3e3-7104c5ade670-result.json │ ├── 45258912-c3d0-4bba-b989-1e3fada9a926-result.json │ ├── 4647a69c-4725-4457-8a25-b050b3bf0bb6-container.json │ ├── 4d5f1584-7524-423c-ba18-85748b60162e-result.json │ ├── 51651fa9-fddb-4a2b-af6c-963d6a8434c7-container.json │ ├── 5aa4107f-2f8b-4e1f-b2e3-e0f9aa18ed46-result.json │ ├── 5ba4f1cd-6b30-4f00-8de9-e1065e8e6d35-result.json │ ├── 5c1b5899-1eef-49bc-b0ab-eb77ba20c527-container.json │ ├── 5dab871f-8f6a-44a7-a495-080e98cd4212-result.json │ ├── 6245e51f-71c5-47d9-aded-1b8bf8192ac6-attachment.txt │ ├── 731bc18c-82f9-4cdf-af9c-f7038d17c9ee-result.json │ ├── 7d344dc5-3fe2-4461-8ef5-f00b5535e849-result.json │ ├── 7d3c66ed-c6d3-410a-98e2-5f6b085ad8e4-container.json │ ├── 7dd62fb1-ea9d-4166-81a3-35f5df15977e-container.json │ ├── 80a6a4e8-925c-4f47-b0be-98047105546c-result.json │ ├── 87ba29d5-cc41-4db5-acaa-3fc920da1064-result.json │ ├── 88eac872-f27f-432c-b448-4801fc9b359c-result.json │ ├── 8b104685-b739-4305-ac21-4a41cbcdb50b-container.json │ ├── 8be4ce2d-e17b-4a2d-9172-6e42d2bd7b71-attachment.txt │ ├── 96e5a1f1-3de1-47ca-bd11-41837f87eefa-container.json │ ├── 97a1c9fb-596c-4c97-859b-9efd965d1d3a-container.json │ ├── 98a7374f-0743-4b64-8a48-270f75841269-container.json │ ├── a2560e91-4446-4b68-8309-56f4167fae61-container.json │ ├── a2feab51-69ef-403f-bf3d-eb8aa67ebca7-container.json │ ├── a766fb96-fc50-410c-aab0-adf4d4f712d2-container.json │ ├── a8c4fdf1-b2a6-4c58-984c-e6d9ae1e2374-container.json │ ├── af02b8b7-3925-4678-b8ff-84936ea22b8e-result.json │ ├── b70d737e-1d07-4dd1-84f8-53dbe040fc6e-container.json │ ├── c052b6bb-ec2b-42fc-a4f7-e3d587d56402-result.json │ ├── c3c996d7-2e8d-4b96-aa1e-2a941c568ac5-result.json │ ├── d215575b-67d6-44c8-a840-258aa2b41e2f-container.json │ ├── d29659e4-f8bc-49a1-bd41-236b80755237-container.json │ ├── d30c37dd-47fc-4292-83a0-8693c7ae83df-result.json │ ├── d72e7d59-5f8b-458a-9f1d-d487eeb91524-container.json │ ├── d917c678-9900-40af-ab75-49a7640ec461-container.json │ ├── dc12eccf-22de-4b43-906a-ad44172689bc-container.json │ ├── df29e220-83bc-47b4-aa0b-bfbc96077006-container.json │ ├── ed43be7e-c3b9-412f-adb6-9766de61b7b7-container.json │ └── ed6b337e-588f-4215-8048-b2b656eadd14-container.json ├── test_course.html ├── test_homework.html ├── test_login.html ├── test_message.html └── test_smoke.html ├── run.py ├── tests ├── test_course.py ├── test_homework.py ├── test_login.py └── test_message.py ├── 课堂派web测试用例.xlsx └── 课堂派项目介绍.md /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /workspace.xml -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/课堂派web.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # web_automation_testing 2 | 基于python+pytest+Selenium+allure,完成web自动化测试框架的搭建,并可以在jenkins上持续集成,应用于课堂派web自动化测试项目中,取得良好效果 3 | -------------------------------------------------------------------------------- /common/base_page.py: -------------------------------------------------------------------------------- 1 | """ 2 | base_page 3 | 页面对象有一些共同的基本操作,可以封装起来,并可以在基本操作当中,加上日志和截图的处理 4 | 1.查找元素,都需要等待 5 | 2.alert弹出框,窗口的切换 6 | 3.鼠标操作 7 | 4.上传文件 8 | """ 9 | import os 10 | import logging 11 | from selenium.webdriver import Chrome 12 | from selenium.webdriver.support import expected_conditions 13 | from selenium.webdriver.support.wait import WebDriverWait 14 | from selenium.webdriver import ActionChains 15 | from config.config import IMAGE_PATH 16 | from datetime import datetime 17 | from pywinauto import Desktop 18 | import time 19 | 20 | 21 | class BasePage: 22 | 23 | def __init__(self, driver: Chrome): # 函数注解 24 | self.driver = driver 25 | 26 | def find(self, locator): 27 | """查找元素""" 28 | try: 29 | e = self.driver.find_element(*locator) 30 | except Exception as err: 31 | # 没有找到元素 32 | logging.error(f"元素定位失败:{err}") 33 | # 截图 34 | self.save_screenshot() 35 | else: 36 | return e 37 | 38 | def save_screenshot(self): 39 | """截图""" 40 | # 路径拼接 41 | # 时间戳命名,防止覆盖 42 | ts_str = datetime.now().strftime("%y-%m_%d-%H-%M-%S") 43 | file_name = os.path.join(IMAGE_PATH, ts_str) + '.png' 44 | self.driver.save_screenshot(file_name) 45 | return self 46 | 47 | def find_and_red(self, locator): 48 | """定位元素并标红,装饰器实现""" 49 | try: 50 | e = self.driver.find_element(*locator) 51 | js_code = "arguments[0].style.borderColor='red';" 52 | self.driver.execute_script(js_code, e) 53 | except Exception as err: 54 | logging.error(f"元素定位失败:{err}") 55 | self.save_screenshot() 56 | else: 57 | return e 58 | 59 | def wait_element_clickable(self, locator, timeout=20, poll_frequency=0.2): 60 | """等待元素可以被点击""" 61 | wait = WebDriverWait(self.driver, timeout, poll_frequency) 62 | try: 63 | e = wait.until(expected_conditions.element_to_be_clickable(locator)) 64 | except Exception as err: 65 | logging.error(f"元素定位失败:{err}") 66 | self.save_screenshot() 67 | else: 68 | return e 69 | 70 | def wait_element_visible(self, locator, timeout=20, poll_frequency=0.2): 71 | """等待元素可见""" 72 | wait = WebDriverWait(self.driver, timeout, poll_frequency) 73 | try: 74 | e = wait.until(expected_conditions.visibility_of_element_located(locator)) 75 | except Exception as err: 76 | logging.error(f"元素定位失败:{err}") 77 | self.save_screenshot() 78 | else: 79 | return e 80 | 81 | def wait_element_present(self, locator, timeout=20, poll_frequency=0.2): 82 | """等待元素被加载""" 83 | wait = WebDriverWait(self.driver, timeout, poll_frequency) 84 | try: 85 | e = wait.until(expected_conditions.presence_of_element_located(locator)) 86 | except Exception as err: 87 | logging.error(f"元素定位失败:{err}") 88 | self.save_screenshot() 89 | else: 90 | return e 91 | 92 | def click_element(self, locator): 93 | """点击某个元素""" 94 | e = self.wait_element_clickable(locator) 95 | e.click() 96 | return self 97 | 98 | def double_click(self, locator): 99 | """双击某个元素""" 100 | e = self.wait_element_clickable(locator) 101 | ac = ActionChains(self.driver) 102 | ac.double_click(e).perform() 103 | return self 104 | 105 | def move_to(self, locator): 106 | """鼠标悬停""" 107 | e = self.find(locator) 108 | ac = ActionChains(self.driver) 109 | ac.move_to_element(e).perform() 110 | return self 111 | 112 | def switch_to_frame(self, e, wait=False): 113 | """iframe切换,内嵌网页""" 114 | if not wait: 115 | self.driver.switch_to.frame(e) 116 | return self 117 | wait = WebDriverWait(self.driver, 30) 118 | wait.until(expected_conditions.frame_to_be_available_and_switch_to_it(e)) 119 | return self 120 | 121 | def add_file(self, file_path): 122 | """添加文件""" 123 | app = Desktop() 124 | dialog = app['打开'] 125 | time.sleep(2) 126 | dialog["Edit"].type_keys(file_path) 127 | dialog["Button"].click() 128 | 129 | def clear_input_box(self, locator): 130 | input_box = self.find(locator) 131 | try: 132 | input_box.clear() 133 | except Exception as err: 134 | logging.error(f"输入框清空失败:{err}") 135 | finally: 136 | return input_box 137 | 138 | 139 | if __name__ == '__main__': 140 | pass 141 | # ts_str = datetime.now().strftime("%y-%m_%d-%H-%M-%S") 142 | # file_name = os.path.join(IMAGE_PATH, ts_str) + '.png' 143 | # print(file_name) 144 | -------------------------------------------------------------------------------- /config/config.py: -------------------------------------------------------------------------------- 1 | """ 2 | 配置文件: 3 | 存放常量 4 | """ 5 | import os 6 | 7 | # 隐式等待时间 8 | IMPLICTLY_WAIT_TIMEOUT = 20 9 | # host 10 | HOST = "https://www.ketangpai.com" 11 | # 项目根地址 12 | ROOT_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 13 | # 报告地址 14 | REPORTS_PATH = os.path.join(ROOT_PATH, "reports") 15 | # image_path 保存截图的路径 16 | IMAGE_PATH = os.path.join(REPORTS_PATH, "screeshots") 17 | # 用于文件上传功能的文件地址 18 | FILES_PATH = os.path.join(ROOT_PATH, "files") 19 | 20 | if __name__ == '__main__': 21 | print(IMAGE_PATH) 22 | -------------------------------------------------------------------------------- /conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from selenium import webdriver 3 | from config import config 4 | from pages.login_page import LoginPage 5 | from pages.main_page import MainPage 6 | from data.login_data import cases_success 7 | from data.course_data import cases_success as join_cs 8 | 9 | 10 | @pytest.fixture(scope="class") 11 | def browser(): 12 | """启动和关闭浏览器""" 13 | # 初始化浏览器 14 | driver = webdriver.Chrome() 15 | # 设置隐式等待 16 | driver.implicitly_wait(config.IMPLICTLY_WAIT_TIMEOUT) 17 | # 浏览器页面最大化 18 | driver.maximize_window() 19 | # 返回一个浏览器对象 20 | yield driver 21 | driver.quit() 22 | 23 | 24 | @pytest.fixture(scope="class") 25 | def login_page(browser): 26 | """已登录""" 27 | login_page = LoginPage(browser) 28 | user_info = cases_success[0] 29 | login_page.get().login(user_info["mobile"], user_info["password"]) 30 | yield browser 31 | 32 | 33 | @pytest.fixture(scope="class") 34 | def join_course(login_page): 35 | """已加入某课程""" 36 | main_page = MainPage(login_page) 37 | course_code_info = join_cs[0] 38 | main_page.get().input_class_code(course_code_info["course_code"]).sure_join_course() 39 | main_page.get() # 刷新页面:如果已加入课程,刷新页面节约时间 40 | yield login_page 41 | 42 | 43 | @pytest.fixture(scope="class") 44 | def enter_students_page(join_course): 45 | """进入学生页面""" 46 | MainPage(join_course).enter_class().click_classmates() 47 | yield join_course 48 | 49 | 50 | @pytest.fixture(scope="class") 51 | def enter_homework_page(join_course): 52 | """进入homework页面""" 53 | MainPage(join_course).enter_class().click_upload_homework() 54 | yield join_course 55 | -------------------------------------------------------------------------------- /data/course_data.py: -------------------------------------------------------------------------------- 1 | """ 2 | 课堂模块测试用例: 3 | 1.加入课堂功能 4 | 2.进入课堂功能 5 | 2.退出课堂功能 6 | """ 7 | cases_success = [{"course_code": "P69UVV", "password": "python123", 8 | "expected1": "加入课堂成功", "expected2": "P69UVV", "expected3": "课程退课成功"}] 9 | 10 | join_cases_success = [ 11 | {"course_code": "P69UVV", "password": "python123"} 12 | ] 13 | 14 | join_cases_error = [ 15 | {"course_code": "123", "expected": "加课验证码必须是6位字符"}, 16 | {"course_code": "123456", "expected": "该加课码不存在或者已经失效"}, 17 | ] 18 | 19 | exit_cases_error = [ 20 | {"password": "zxz", "expected": "密码错误"} 21 | ] 22 | -------------------------------------------------------------------------------- /data/homework_data.py: -------------------------------------------------------------------------------- 1 | """ 2 | 作业模块测试用例: 3 | 1.提交作业 4 | 2.作业留言 5 | 3.查看作业提交情况 6 | """ 7 | import os 8 | from config.config import FILES_PATH 9 | 10 | cases_success = [ 11 | {"file_path": FILES_PATH + r'\txt文档.txt', 12 | "message": "第1次提交作业!", 13 | "expected1": "作业提交成功", 14 | "expected2": "第1次提交作业!", 15 | "expected3": '添加了 "txt文档.txt" 并提交'}, 16 | {"file_path": FILES_PATH + r'\txt文档.txt', 17 | "message": "第2次提交作业!", 18 | "expected1": "作业提交成功", 19 | "expected2": "第2次提交作业!", 20 | "expected3": '添加了 "txt文档.txt" 并提交'}, 21 | ] 22 | 23 | 24 | file_cases_success = [ 25 | {"file_path": FILES_PATH + r'\png图片.png', "expected": "作业提交成功"}, 26 | {"file_path": FILES_PATH + r'\py代码.py', "expected": "作业提交成功"}, 27 | {"file_path": FILES_PATH + r'\txt文档.txt', "expected": "作业提交成功"}, 28 | {"file_path": FILES_PATH + r'\xlsx文件.xlsx', "expected": "作业提交成功"}, 29 | {"file_path": FILES_PATH + r'\压缩包.rar', "expected": "作业提交成功"}, 30 | ] 31 | 32 | if __name__ == '__main__': 33 | # F:\课堂派web自动化项目\files\png图片.png 34 | print(FILES_PATH) 35 | file_path = FILES_PATH + r'\压缩包.rar' 36 | print(file_path) 37 | print(os.path.join(FILES_PATH, "png图片.png")) 38 | -------------------------------------------------------------------------------- /data/login_data.py: -------------------------------------------------------------------------------- 1 | """ 2 | 课堂派登录测试用例 3 | """ 4 | cases_success = [ 5 | {"mobile": "18740865632", "password": "python123", "expected": "东何"} 6 | ] 7 | 8 | cases_error = [ 9 | {"mobile": "", "password": "12", "expected": "账号不能为空"}, 10 | {"mobile": "19244533103", "password": "", "expected": "密码不能为空"}, 11 | {"mobile": "19244533103", "password": "zx", "expected": "密码有效长度是6到30个字符"}, 12 | {"mobile": "19244533103", "password": "123456", "expected": "用户不存在"} 13 | ] 14 | 15 | -------------------------------------------------------------------------------- /data/send_message_data.py: -------------------------------------------------------------------------------- 1 | """ 2 | 发送私信测试用例 3 | """ 4 | cases_success = [ 5 | {"message": "你好!", "expected": "你好!"}, 6 | {"message": "做个朋友吧~", "expected": "做个朋友吧~"} 7 | ] -------------------------------------------------------------------------------- /files/png图片.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/donghe123178/web_automation_testing/1be5590eb4fe30055240506ebc7231d3cc457634/files/png图片.png -------------------------------------------------------------------------------- /files/py代码.py: -------------------------------------------------------------------------------- 1 | """ 2 | 课堂派加入课堂测试用例 3 | """ 4 | cases_success = [ 5 | {"add_class_code": "P69UVV", "expected": "加入课堂成功"} 6 | ] 7 | 8 | cases_error = [ 9 | {"add_class_code": "123", "expected": "加课验证码必须是6位字符"}, 10 | {"add_class_code": "123456", "expected": "该加课码不存在或者已经失效"}, 11 | ] 12 | 13 | -------------------------------------------------------------------------------- /files/txt文档.txt: -------------------------------------------------------------------------------- 1 | 必须按时工厂倒闭扯上关系帮我出个是,axgcgbsbxjhhbxsbxhq -------------------------------------------------------------------------------- /files/xlsx文件.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/donghe123178/web_automation_testing/1be5590eb4fe30055240506ebc7231d3cc457634/files/xlsx文件.xlsx -------------------------------------------------------------------------------- /files/压缩包.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/donghe123178/web_automation_testing/1be5590eb4fe30055240506ebc7231d3cc457634/files/压缩包.rar -------------------------------------------------------------------------------- /pages/class_page.py: -------------------------------------------------------------------------------- 1 | from selenium.webdriver.common.by import By 2 | from common.base_page import BasePage 3 | from pages.students_page import StudentsPage 4 | from pages.homework_page import HomeWorkPage 5 | # from pages.main_page import MainPage 6 | 7 | 8 | class ClassPage(BasePage): 9 | """课堂页面操作: 10 | 1.定位同学,点击,跳转至students页面 11 | 2.定位作业,点击,定位作业标题,点击,跳转至homework页面 12 | 3.获取课程码:定位课程码 13 | 4.定位课堂,点击,回到main主页 14 | """ 15 | classmates_locator = (By.XPATH, '//li[@class="li5"]//a') 16 | homework_locator = (By.XPATH, '//a[text()="作业"]') 17 | homework_title_locator = (By.XPATH, '//h3[@class="work-title "]//a') 18 | class_btn_locator = (By.XPATH, '//p//a') 19 | course_code_locator = (By.XPATH, '(//div[contains(@class,"codetip")])[3]') 20 | 21 | def click_classmates(self): 22 | """点击同学""" 23 | e = self.find(self.classmates_locator) 24 | e.click() 25 | return StudentsPage(self.driver) 26 | 27 | def click_upload_homework(self): 28 | """点击作业-上传作业""" 29 | e1 = self.find(self.homework_locator) 30 | e1.click() 31 | e2 = self.find(self.homework_title_locator) 32 | e2.click() 33 | return HomeWorkPage(self.driver) 34 | 35 | # def click_class_btn(self): 36 | # """点击课堂,跳转至主页""" 37 | # e = self.find(self.class_btn_locator) 38 | # e.click() 39 | # return MainPage(self.driver) 40 | 41 | def get_course_code(self): 42 | """获取课程码""" 43 | e = self.find(self.course_code_locator) 44 | return e.text 45 | -------------------------------------------------------------------------------- /pages/homework_page.py: -------------------------------------------------------------------------------- 1 | from config import config 2 | from selenium.webdriver.common.by import By 3 | from common.base_page import BasePage 4 | import logging 5 | import time 6 | 7 | 8 | class HomeWorkPage(BasePage): 9 | """作业页面操作: 10 | 1. 添加作业文件 11 | 2. 提交 12 | 3. 作业留言: 13 | 6.定位作业留言按钮,点击
14 | 7.定位留言输入框
8.输入留言
15 | 9.定位保存按钮,点击提交
16 | 10.定位作业留言按钮,获取留言信息,断言 17 | 4. 查看提交日志 18 | 19 | """ 20 | url = config.HOST + "/Homework/handup/homeworkid/MDAwMDAwMDAwMLScz5mHqa9s.html" 21 | 22 | # 更新提交 23 | submit_btn_locator = (By.XPATH, '//a[contains(@class, "tj-btn")]') 24 | new_submit_btn1_locator = (By.XPATH, '//a[@class="new-tj1"]') 25 | new_submit_btn2_locator = (By.XPATH, '//a[contains(@class, "new-tj2")]') 26 | 27 | sure_btn_locator = (By.XPATH, '//div[@class="btns"]//a[contains(@class, "active")]') 28 | 29 | add_files_btn_locator = (By.XPATH, '//input[@name="file"]') 30 | 31 | delete_file_btn_locator = (By.XPATH, '//a[text()="删除"]') 32 | 33 | success_message_locator = (By.XPATH, '//div[@class="weui_dialog_bd"]') 34 | known_locator = (By.XPATH, '//a[contains(@class, "weui_btn_dialog")]') 35 | 36 | message_btn_locator = (By.XPATH, '//span[@class="s2"]') 37 | comment_locator = (By.XPATH, '//textarea[@id="comment"]') 38 | save_btn_locator = (By.XPATH, '//textarea[@id="comment"]/following-sibling::a') 39 | 40 | view_status_locator = (By.XPATH, '//a[@class="togglesee"]') 41 | log_locator = (By.XPATH, '//div[@class="content"]//li//p') 42 | 43 | def get(self): 44 | """刷新页面""" 45 | self.driver.get(self.url) 46 | return self 47 | 48 | def upload_files(self, file_path): 49 | """上传作业""" 50 | try: 51 | e1 = self.find(self.new_submit_btn1_locator) 52 | e1.click() 53 | e2 = self.find(self.sure_btn_locator) 54 | e2.click() 55 | except Exception as err: 56 | logging.error(f"点击更新提交失败:{err}") 57 | e3 = self.find(self.add_files_btn_locator) 58 | e3.send_keys(file_path) 59 | return self 60 | 61 | def delete_file(self): 62 | """删除文件""" 63 | e = self.find(self.delete_file_btn_locator) 64 | e.click() 65 | return self 66 | 67 | def click_submit_files(self): 68 | """点击作业提交""" 69 | time.sleep(2) 70 | try: 71 | self.click_element(self.new_submit_btn2_locator) 72 | except Exception as err: 73 | logging.error(f"点击更新提交失败:{err}") 74 | self.click_element(self.submit_btn_locator) 75 | return self 76 | 77 | def get_success_message(self): 78 | """获取作业成功提交信息""" 79 | e = self.find(self.success_message_locator) 80 | return e.text 81 | 82 | def click_known(self): 83 | """点击知道了""" 84 | e = self.find(self.known_locator) 85 | e.click() 86 | return self 87 | 88 | def comment(self, message): 89 | """作业留言""" 90 | message_elem = self.find(self.message_btn_locator) 91 | message_elem.click() 92 | input_elem = self.clear_input_box(self.comment_locator) 93 | input_elem.send_keys(message) 94 | self.click_element(self.save_btn_locator) 95 | return self 96 | 97 | def get_comment(self): 98 | """获取留言信息""" 99 | e = self.find(self.message_btn_locator) 100 | return e.text 101 | 102 | def view_status(self): 103 | """查看提交日志""" 104 | e = self.find(self.view_status_locator) 105 | e.click() 106 | log_elem = self.find(self.log_locator) 107 | return log_elem.text 108 | -------------------------------------------------------------------------------- /pages/login_page.py: -------------------------------------------------------------------------------- 1 | from config import config 2 | from selenium.webdriver.common.by import By 3 | from common.base_page import BasePage 4 | 5 | 6 | class LoginPage(BasePage): 7 | """登录页面操作: 8 | 1. 刷新登录页面 9 | 2. 登录操作:定位用户名、输入手机号、定位密码、输入密码、定位登录、点击提交 10 | 3. 获取返回的信息 11 | """ 12 | url = config.HOST + "/User/login.html" 13 | 14 | phone_locator = (By.NAME, "account") 15 | pwd_locator = (By.NAME, "pass") 16 | login_btn_locator = (By.XPATH, '//a[contains(@class, "btn-btn")]') 17 | error_msg_locator = (By.XPATH, '//p[@class="error-tips"]') 18 | 19 | def get(self): 20 | """访问login页面""" 21 | self.driver.get(self.url) 22 | return self 23 | 24 | def login(self, mobile, pwd): 25 | """登录操作""" 26 | username_elem = self.find(self.phone_locator) 27 | username_elem.send_keys(mobile) 28 | pwd_elem = self.find(self.pwd_locator) 29 | pwd_elem.send_keys(pwd) 30 | self.click_element(self.login_btn_locator) 31 | return self 32 | 33 | def get_error_msg(self): 34 | """获取错误信息""" 35 | e = self.find(self.error_msg_locator) 36 | return e.text 37 | -------------------------------------------------------------------------------- /pages/main_page.py: -------------------------------------------------------------------------------- 1 | from config import config 2 | from selenium.webdriver.common.by import By 3 | from common.base_page import BasePage 4 | from pages.class_page import ClassPage 5 | 6 | 7 | class MainPage(BasePage): 8 | """主页页面操作: 9 | 1. 刷新首页 10 | 2. 输入加课码:定位加入课程,点击,定位加课验证码输入框,输入加课码 11 | 3. 定位确定按钮,点击确定 12 | 4. 定位取消按钮,点击取消 13 | 5. 获取错误信息 14 | 6. 获取成功信息 15 | 7. 退课操作:定位更多,点击,定位退课,点击,定位登录密码输入框,输入密码,定位退课按钮,点击提交 16 | 8. 进入班级操作:定位班级,点击跳转至class界面 17 | 9. 获取用户账户信息:定位 18 | """ 19 | url = config.HOST + "/Main/index.html" 20 | 21 | user_account_locator = (By.XPATH, '//img[@class="avatar"]') 22 | 23 | add_class_btn_locator = (By.XPATH, '//div[contains(@class, "ktcon1l")]') 24 | input_add_class_code_locator = (By.XPATH, '//div[@class="chuangjiankccon"]//input[@type="text"]') 25 | sure_btn_locator = (By.XPATH, '//li[@class="cjli2"]//a[contains(@class, "btn-positive")]') 26 | 27 | error_msg_locator = (By.XPATH, '//div[@id="error-tip"]//span') 28 | success_msg_locator = (By.XPATH, '//div[@id="show-tip"]//span') 29 | 30 | more_btn_locator = (By.XPATH, '//a[contains(@class, "kdmore")]//span') 31 | exit_class_btn_01_locator = (By.XPATH, '//li[contains(@class, "kdli3")]//a') 32 | cancel_btn_locator = (By.XPATH, '//li[@class="cjli1"]//a') 33 | input_pwd_locator = (By.XPATH, '//input[@type="password"]') 34 | exit_class_btn_02_locator = (By.XPATH, '//li[@class="dli2"]//a[contains(@class, "btn-positive")]') 35 | 36 | enter_class_locator = (By.XPATH, '//a[@class="jumptoclass"]') 37 | 38 | course_code_locator = (By.XPATH, '//p[contains(@class,"invitecode")]') 39 | 40 | def get(self): 41 | """访问首页""" 42 | self.driver.get(self.url) 43 | return self 44 | 45 | def input_class_code(self, class_code): 46 | """输入课程码""" 47 | self.click_element(self.add_class_btn_locator) 48 | e = self.wait_element_visible(self.input_add_class_code_locator) 49 | e.send_keys(class_code) 50 | return self 51 | 52 | def sure_join_course(self): 53 | """点击确定加入""" 54 | self.click_element(self.sure_btn_locator) 55 | return self 56 | 57 | def cancel_class(self): 58 | """取消加入课程操作""" 59 | e = self.find(self.cancel_btn_locator) 60 | e.click() 61 | return self 62 | 63 | def get_error_msg(self): 64 | """获取错误信息""" 65 | e = self.wait_element_visible(self.error_msg_locator) 66 | return e.text 67 | 68 | def get_success_msg(self): 69 | """获取成功信息""" 70 | e = self.wait_element_visible(self.success_msg_locator) 71 | return e.text 72 | 73 | def click_more_btn(self): 74 | """点击更多按钮""" 75 | e = self.find(self.more_btn_locator) 76 | e.click() 77 | return self 78 | 79 | def exit_course(self, password): 80 | """退出课程""" 81 | # 点击退课按钮 82 | e1 = self.find(self.exit_class_btn_01_locator) 83 | e1.click() 84 | # 输入密码 85 | e = self.wait_element_visible(self.input_pwd_locator) 86 | e.send_keys(password) 87 | # 点击退课按钮 88 | self.click_element(self.exit_class_btn_02_locator) 89 | return self 90 | 91 | def enter_class(self): 92 | """进入班级操作""" 93 | e = self.find(self.enter_class_locator) 94 | e.click() 95 | return ClassPage(self.driver) 96 | 97 | def get_user_account(self): 98 | """获取用户的账号信息""" 99 | e = self.find(self.user_account_locator) 100 | return e.get_attribute("title") 101 | 102 | def get_course_code(self): 103 | """获取课程码""" 104 | e = self.find(self.course_code_locator) 105 | return e.text 106 | -------------------------------------------------------------------------------- /pages/students_page.py: -------------------------------------------------------------------------------- 1 | from config import config 2 | from selenium.webdriver.common.by import By 3 | from common.base_page import BasePage 4 | import time 5 | 6 | 7 | class StudentsPage(BasePage): 8 | """Students页面操作:私信操作 9 | 1.定位全部学生,点击 10 | 2.定位第一个学生,鼠标悬停 11 | 3.定位call图标,点击 12 | 4.定位会话输入框 13 | 5.输入消息 14 | 6.定位发送按钮 15 | 7.点击提交,等待发送成功 16 | 8.定位发送的文本,最新的 17 | """ 18 | url = config.HOST + "/StudentsV2/index/courseid/MDAwMDAwMDAwMLR2vd6Gz8mw.html" 19 | 20 | all_students_locator = (By.XPATH, '//li[contains(@class, "all")]') 21 | fist_student_locator = (By.XPATH, '//p[@class="studentavatar"]/..') 22 | call_locator = (By.XPATH, '//a[@class="call"]') 23 | input_message_locator = (By.XPATH, '//textarea[@class="ps-container"]') 24 | send_btn_locator = (By.XPATH, '//a[contains(@class,"btn-positive")]') 25 | message_locator =(By.XPATH, '(//div[@class="text"])[last()]') 26 | 27 | def get(self): 28 | """刷新页面""" 29 | self.driver.get(self.url) 30 | return self 31 | 32 | def send_message(self, message): 33 | """私信操作""" 34 | students = self.find(self.all_students_locator) 35 | students.click() 36 | self.move_to(self.fist_student_locator) 37 | call_btn = self.wait_element_visible(self.call_locator) 38 | call_btn.click() 39 | input_message = self.find(self.input_message_locator) 40 | input_message.send_keys(message) 41 | self.click_element(self.send_btn_locator) 42 | # time.sleep(10) 43 | e = self.find(self.message_locator) 44 | return e.text 45 | 46 | 47 | -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | markers = 3 | success 4 | smoke 5 | error 6 | login 7 | course 8 | message 9 | homework 10 | 11 | -------------------------------------------------------------------------------- /reports/assets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Helvetica, Arial, sans-serif; 3 | font-size: 12px; 4 | /* do not increase min-width as some may use split screens */ 5 | min-width: 800px; 6 | color: #999; 7 | } 8 | 9 | h1 { 10 | font-size: 24px; 11 | color: black; 12 | } 13 | 14 | h2 { 15 | font-size: 16px; 16 | color: black; 17 | } 18 | 19 | p { 20 | color: black; 21 | } 22 | 23 | a { 24 | color: #999; 25 | } 26 | 27 | table { 28 | border-collapse: collapse; 29 | } 30 | 31 | /****************************** 32 | * SUMMARY INFORMATION 33 | ******************************/ 34 | 35 | #environment td { 36 | padding: 5px; 37 | border: 1px solid #E6E6E6; 38 | } 39 | 40 | #environment tr:nth-child(odd) { 41 | background-color: #f6f6f6; 42 | } 43 | 44 | /****************************** 45 | * TEST RESULT COLORS 46 | ******************************/ 47 | span.passed, .passed .col-result { 48 | color: green; 49 | } 50 | span.skipped, span.xfailed, span.rerun, .skipped .col-result, .xfailed .col-result, .rerun .col-result { 51 | color: orange; 52 | } 53 | span.error, span.failed, span.xpassed, .error .col-result, .failed .col-result, .xpassed .col-result { 54 | color: red; 55 | } 56 | 57 | 58 | /****************************** 59 | * RESULTS TABLE 60 | * 61 | * 1. Table Layout 62 | * 2. Extra 63 | * 3. Sorting items 64 | * 65 | ******************************/ 66 | 67 | /*------------------ 68 | * 1. Table Layout 69 | *------------------*/ 70 | 71 | #results-table { 72 | border: 1px solid #e6e6e6; 73 | color: #999; 74 | font-size: 12px; 75 | width: 100% 76 | } 77 | 78 | #results-table th, #results-table td { 79 | padding: 5px; 80 | border: 1px solid #E6E6E6; 81 | text-align: left 82 | } 83 | #results-table th { 84 | font-weight: bold 85 | } 86 | 87 | /*------------------ 88 | * 2. Extra 89 | *------------------*/ 90 | 91 | .log:only-child { 92 | height: inherit 93 | } 94 | .log { 95 | background-color: #e6e6e6; 96 | border: 1px solid #e6e6e6; 97 | color: black; 98 | display: block; 99 | font-family: "Courier New", Courier, monospace; 100 | height: 230px; 101 | overflow-y: scroll; 102 | padding: 5px; 103 | white-space: pre-wrap 104 | } 105 | div.image { 106 | border: 1px solid #e6e6e6; 107 | float: right; 108 | height: 240px; 109 | margin-left: 5px; 110 | overflow: hidden; 111 | width: 320px 112 | } 113 | div.image img { 114 | width: 320px 115 | } 116 | div.video { 117 | border: 1px solid #e6e6e6; 118 | float: right; 119 | height: 240px; 120 | margin-left: 5px; 121 | overflow: hidden; 122 | width: 320px 123 | } 124 | div.video video { 125 | overflow: hidden; 126 | width: 320px; 127 | height: 240px; 128 | } 129 | .collapsed { 130 | display: none; 131 | } 132 | .expander::after { 133 | content: " (show details)"; 134 | color: #BBB; 135 | font-style: italic; 136 | cursor: pointer; 137 | } 138 | .collapser::after { 139 | content: " (hide details)"; 140 | color: #BBB; 141 | font-style: italic; 142 | cursor: pointer; 143 | } 144 | 145 | /*------------------ 146 | * 3. Sorting items 147 | *------------------*/ 148 | .sortable { 149 | cursor: pointer; 150 | } 151 | 152 | .sort-icon { 153 | font-size: 0px; 154 | float: left; 155 | margin-right: 5px; 156 | margin-top: 5px; 157 | /*triangle*/ 158 | width: 0; 159 | height: 0; 160 | border-left: 8px solid transparent; 161 | border-right: 8px solid transparent; 162 | } 163 | 164 | .inactive .sort-icon { 165 | /*finish triangle*/ 166 | border-top: 8px solid #E6E6E6; 167 | } 168 | 169 | .asc.active .sort-icon { 170 | /*finish triangle*/ 171 | border-bottom: 8px solid #999; 172 | } 173 | 174 | .desc.active .sort-icon { 175 | /*finish triangle*/ 176 | border-top: 8px solid #999; 177 | } 178 | -------------------------------------------------------------------------------- /reports/test_all/0211c339-c64f-42e8-8307-0f9f0814133f-result.json: -------------------------------------------------------------------------------- 1 | {"name": "test_login_error[test_info1]", "status": "passed", "description": "登录失败", "parameters": [{"name": "test_info", "value": "{'mobile': '19244533103', 'password': '', 'expected': '密码不能为空'}"}], "start": 1595077730242, "stop": 1595077736106, "uuid": "233ac7c3-cb93-4f67-b77e-4ce9f13408af", "historyId": "2e413b860ccd28055cdc847242f514e6", "testCaseId": "5fd5da3b3ca8fdf751feb802572e5b42", "fullName": "tests.test_login.TestLogin#test_login_error", "labels": [{"name": "tag", "value": "login"}, {"name": "parentSuite", "value": "tests"}, {"name": "suite", "value": "test_login"}, {"name": "subSuite", "value": "TestLogin"}, {"name": "host", "value": "DESKTOP-83PFO6C"}, {"name": "thread", "value": "12272-MainThread"}, {"name": "framework", "value": "pytest"}, {"name": "language", "value": "cpython3"}, {"name": "package", "value": "tests.test_login"}]} -------------------------------------------------------------------------------- /reports/test_all/10a69e1c-99d2-48d4-ae3a-38620b1d9e42-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "d6e3dc73-6955-4960-b436-c864f6241f1f", "befores": [{"name": "test_info", "status": "passed", "start": 1595077741852, "stop": 1595077741852}], "start": 1595077741852, "stop": 1595077747589} -------------------------------------------------------------------------------- /reports/test_all/1540e390-1fab-4ff5-8d26-c043180e994a-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "7fbfcb72-1bbd-4d61-a264-9d8e21278903", "befores": [{"name": "test_info", "status": "passed", "start": 1595077724520, "stop": 1595077724520}], "start": 1595077724520, "stop": 1595077730221} -------------------------------------------------------------------------------- /reports/test_all/195e7880-743b-4e9d-82cb-4d86ef52ee4b-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "cdf56851-e236-40c9-97d8-bd0910300b57", "children": ["ea51762e-f2e5-40d2-a2e6-35ab54db5598", "1bb6a023-b927-4e51-ae19-7ff6731bbf69", "c9ca5fc2-fa58-407b-bc6b-88d7dc279774", "e24c4dda-7f3e-4387-a8f9-5c0e59b1dc40", "68795572-15bc-45c4-86d7-a77f716ed32d", "a2e559fa-de7c-45fd-898a-86a80b706e2c", "dcac2979-e430-4e54-9499-2d2a4db741bf"], "befores": [{"name": "join_course", "status": "passed", "start": 1595077633511, "stop": 1595077635610}], "afters": [{"name": "join_course::0", "status": "passed", "start": 1595077707990, "stop": 1595077707990}], "start": 1595077633511, "stop": 1595077707990} -------------------------------------------------------------------------------- /reports/test_all/1cc0f639-8e8c-46fa-b0ca-eccbb88d481a-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "8d51739d-c4e5-455b-839c-a5af14f3c0c9", "befores": [{"name": "test_info", "status": "passed", "start": 1595077683787, "stop": 1595077683787}], "start": 1595077683787, "stop": 1595077688183} -------------------------------------------------------------------------------- /reports/test_all/2979e93a-2452-458e-886d-dcd6dd045e9a-result.json: -------------------------------------------------------------------------------- 1 | {"name": "test_add_success[test_info0]", "status": "passed", "description": "加课失败", "parameters": [{"name": "test_info", "value": "{'course_code': '123', 'expected': '加课验证码必须是6位字符'}"}], "start": 1595077594126, "stop": 1595077595025, "uuid": "dc0a2f15-4245-49c2-9011-283adcf7e023", "historyId": "4766c2a2946570b41773bab31abd5372", "testCaseId": "c00fc0a16e4502b552e092a5e62abb28", "fullName": "tests.test_course.TestCourse#test_add_success", "labels": [{"name": "tag", "value": "error"}, {"name": "tag", "value": "course"}, {"name": "parentSuite", "value": "tests"}, {"name": "suite", "value": "test_course"}, {"name": "subSuite", "value": "TestCourse"}, {"name": "host", "value": "DESKTOP-83PFO6C"}, {"name": "thread", "value": "12272-MainThread"}, {"name": "framework", "value": "pytest"}, {"name": "language", "value": "cpython3"}, {"name": "package", "value": "tests.test_course"}]} -------------------------------------------------------------------------------- /reports/test_all/2c0512bc-f100-4275-9e03-5312c8699682-result.json: -------------------------------------------------------------------------------- 1 | {"name": "test_upload_homework_success[test_info0]", "status": "passed", "description": "提交作业成功", "parameters": [{"name": "test_info", "value": "{'file_path': 'F:\\\\课堂派web\\\\files\\\\png图片.png', 'expected': '作业提交成功'}"}], "start": 1595077688188, "stop": 1595077691846, "uuid": "c9ca5fc2-fa58-407b-bc6b-88d7dc279774", "historyId": "d505c9fb039a1eeea887eac28fd7ee1f", "testCaseId": "b7b8d14c0311e805effa61e23a4d5200", "fullName": "tests.test_homework.TestHomework#test_upload_homework_success", "labels": [{"name": "tag", "value": "homework"}, {"name": "parentSuite", "value": "tests"}, {"name": "suite", "value": "test_homework"}, {"name": "subSuite", "value": "TestHomework"}, {"name": "host", "value": "DESKTOP-83PFO6C"}, {"name": "thread", "value": "12272-MainThread"}, {"name": "framework", "value": "pytest"}, {"name": "language", "value": "cpython3"}, {"name": "package", "value": "tests.test_homework"}]} -------------------------------------------------------------------------------- /reports/test_all/30146b79-9c47-4dff-bc14-e52af2f7435c-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "7f8959c2-483c-4254-b82e-2cca8bed6019", "children": ["896f02b0-d0a1-4a08-ab9d-ea5f6849e4d7", "639f7cd3-d049-44f4-9f55-dfd0ea12351f"], "befores": [{"name": "browser", "status": "passed", "start": 1595077749757, "stop": 1595077759509}], "afters": [{"name": "browser::0", "status": "passed", "start": 1595077772107, "stop": 1595077774330}], "start": 1595077749757, "stop": 1595077774330} -------------------------------------------------------------------------------- /reports/test_all/3fb542d1-74a1-475a-8aac-70bcc09542ce-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "1fa0058c-029b-47d4-96cf-f55ba32b93bb", "befores": [{"name": "test_info", "status": "passed", "start": 1595077590791, "stop": 1595077590791}], "start": 1595077590791, "stop": 1595077594098} -------------------------------------------------------------------------------- /reports/test_all/41576d93-caea-404c-9a92-1f02489994df-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "77e80c88-92f3-428b-8375-a86eb325deb4", "children": ["97fd0361-9fe5-45ec-afe7-6e9ad3493840", "01cf2a92-e652-4900-bbf6-c8aea2c6c57c", "233ac7c3-cb93-4f67-b77e-4ce9f13408af", "9390a059-5e89-40b4-b5d0-25f3275ff712", "6bc0e79f-c9fb-42a3-b9e8-adbebf03bfa3"], "befores": [{"name": "browser", "status": "passed", "start": 1595077710232, "stop": 1595077720053}], "afters": [{"name": "browser::0", "status": "passed", "start": 1595077747590, "stop": 1595077749751}], "start": 1595077710231, "stop": 1595077749751} -------------------------------------------------------------------------------- /reports/test_all/4429863e-9cc5-4f67-a367-af537333daf3-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "a20853d8-ee56-4d1d-a8b9-4b29295b8851", "befores": [{"name": "test_info", "status": "passed", "start": 1595077638700, "stop": 1595077638700}], "start": 1595077638700, "stop": 1595077683760} -------------------------------------------------------------------------------- /reports/test_all/451470ca-99d8-4a80-b3e3-7104c5ade670-result.json: -------------------------------------------------------------------------------- 1 | {"name": "test_send_message_success[test_info0]", "status": "passed", "parameters": [{"name": "test_info", "value": "{'message': '你好!', 'expected': '你好!'}"}], "start": 1595077767490, "stop": 1595077769836, "uuid": "896f02b0-d0a1-4a08-ab9d-ea5f6849e4d7", "historyId": "abe8c4f75c900690c4183b64b79c1454", "testCaseId": "c88b5e3ca488eb36d0830d18de2448b4", "fullName": "tests.test_message.TestSendMessage#test_send_message_success", "labels": [{"name": "tag", "value": "success"}, {"name": "tag", "value": "smoke"}, {"name": "tag", "value": "message"}, {"name": "parentSuite", "value": "tests"}, {"name": "suite", "value": "test_message"}, {"name": "subSuite", "value": "TestSendMessage"}, {"name": "host", "value": "DESKTOP-83PFO6C"}, {"name": "thread", "value": "12272-MainThread"}, {"name": "framework", "value": "pytest"}, {"name": "language", "value": "cpython3"}, {"name": "package", "value": "tests.test_message"}]} -------------------------------------------------------------------------------- /reports/test_all/45258912-c3d0-4bba-b989-1e3fada9a926-result.json: -------------------------------------------------------------------------------- 1 | {"name": "test_login_error[test_info3]", "status": "passed", "description": "登录失败", "parameters": [{"name": "test_info", "value": "{'mobile': '19244533103', 'password': '123456', 'expected': '用户不存在'}"}], "start": 1595077741852, "stop": 1595077747587, "uuid": "6bc0e79f-c9fb-42a3-b9e8-adbebf03bfa3", "historyId": "bf2e616a522b10feaad5ac8e0df3ea34", "testCaseId": "5fd5da3b3ca8fdf751feb802572e5b42", "fullName": "tests.test_login.TestLogin#test_login_error", "labels": [{"name": "tag", "value": "login"}, {"name": "parentSuite", "value": "tests"}, {"name": "suite", "value": "test_login"}, {"name": "subSuite", "value": "TestLogin"}, {"name": "host", "value": "DESKTOP-83PFO6C"}, {"name": "thread", "value": "12272-MainThread"}, {"name": "framework", "value": "pytest"}, {"name": "language", "value": "cpython3"}, {"name": "package", "value": "tests.test_login"}]} -------------------------------------------------------------------------------- /reports/test_all/4647a69c-4725-4457-8a25-b050b3bf0bb6-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "546446a0-0a3c-4e4f-976f-91759b6d1cd3", "befores": [{"name": "test_info", "status": "passed", "start": 1595077730241, "stop": 1595077730241}], "start": 1595077730241, "stop": 1595077736108} -------------------------------------------------------------------------------- /reports/test_all/4d5f1584-7524-423c-ba18-85748b60162e-result.json: -------------------------------------------------------------------------------- 1 | {"name": "test_send_message_success[test_info1]", "status": "passed", "parameters": [{"name": "test_info", "value": "{'message': '做个朋友吧~', 'expected': '做个朋友吧~'}"}], "start": 1595077769841, "stop": 1595077772072, "uuid": "639f7cd3-d049-44f4-9f55-dfd0ea12351f", "historyId": "97fc84770ea9bfb9f4a0c12422b4191e", "testCaseId": "c88b5e3ca488eb36d0830d18de2448b4", "fullName": "tests.test_message.TestSendMessage#test_send_message_success", "labels": [{"name": "tag", "value": "success"}, {"name": "tag", "value": "smoke"}, {"name": "tag", "value": "message"}, {"name": "parentSuite", "value": "tests"}, {"name": "suite", "value": "test_message"}, {"name": "subSuite", "value": "TestSendMessage"}, {"name": "host", "value": "DESKTOP-83PFO6C"}, {"name": "thread", "value": "12272-MainThread"}, {"name": "framework", "value": "pytest"}, {"name": "language", "value": "cpython3"}, {"name": "package", "value": "tests.test_message"}]} -------------------------------------------------------------------------------- /reports/test_all/51651fa9-fddb-4a2b-af6c-963d6a8434c7-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "69176db1-b64e-4544-bba2-df7f91ba3742", "befores": [{"name": "test_info", "status": "passed", "start": 1595077736111, "stop": 1595077736111}], "start": 1595077736111, "stop": 1595077741815} -------------------------------------------------------------------------------- /reports/test_all/5aa4107f-2f8b-4e1f-b2e3-e0f9aa18ed46-result.json: -------------------------------------------------------------------------------- 1 | {"name": "test_login_error[test_info2]", "status": "passed", "description": "登录失败", "parameters": [{"name": "test_info", "value": "{'mobile': '19244533103', 'password': 'zx', 'expected': '密码有效长度是6到30个字符'}"}], "start": 1595077736112, "stop": 1595077741813, "uuid": "9390a059-5e89-40b4-b5d0-25f3275ff712", "historyId": "25c5b68ccafe662af29d1bf2a8c3d40a", "testCaseId": "5fd5da3b3ca8fdf751feb802572e5b42", "fullName": "tests.test_login.TestLogin#test_login_error", "labels": [{"name": "tag", "value": "login"}, {"name": "parentSuite", "value": "tests"}, {"name": "suite", "value": "test_login"}, {"name": "subSuite", "value": "TestLogin"}, {"name": "host", "value": "DESKTOP-83PFO6C"}, {"name": "thread", "value": "12272-MainThread"}, {"name": "framework", "value": "pytest"}, {"name": "language", "value": "cpython3"}, {"name": "package", "value": "tests.test_login"}]} -------------------------------------------------------------------------------- /reports/test_all/5ba4f1cd-6b30-4f00-8de9-e1065e8e6d35-result.json: -------------------------------------------------------------------------------- 1 | {"name": "test_login_success[test_info0]", "status": "passed", "description": "登录成功", "parameters": [{"name": "test_info", "value": "{'mobile': '18740865632', 'password': 'python123', 'expected': '东何'}"}], "start": 1595077720058, "stop": 1595077724514, "uuid": "97fd0361-9fe5-45ec-afe7-6e9ad3493840", "historyId": "4e896cf27b653687baceb0f50218ffb8", "testCaseId": "f53b2514489833ab97e9dcb8d0c7049e", "fullName": "tests.test_login.TestLogin#test_login_success", "labels": [{"name": "tag", "value": "success"}, {"name": "tag", "value": "smoke"}, {"name": "tag", "value": "login"}, {"name": "parentSuite", "value": "tests"}, {"name": "suite", "value": "test_login"}, {"name": "subSuite", "value": "TestLogin"}, {"name": "host", "value": "DESKTOP-83PFO6C"}, {"name": "thread", "value": "12272-MainThread"}, {"name": "framework", "value": "pytest"}, {"name": "language", "value": "cpython3"}, {"name": "package", "value": "tests.test_login"}]} -------------------------------------------------------------------------------- /reports/test_all/5c1b5899-1eef-49bc-b0ab-eb77ba20c527-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "d2b95a1d-46b3-4817-a05c-f9274b1e799b", "children": ["f0298da9-eddf-4624-9c72-91cab5e57fdd", "dc0a2f15-4245-49c2-9011-283adcf7e023", "8e370789-8059-42d0-862e-494ae3f01ba6", "42baa144-e0ef-4af1-909a-63d52683493b"], "befores": [{"name": "login_page", "status": "passed", "start": 1595077578253, "stop": 1595077590791}], "afters": [{"name": "login_page::0", "status": "passed", "start": 1595077619298, "stop": 1595077619298}], "start": 1595077578253, "stop": 1595077619298} -------------------------------------------------------------------------------- /reports/test_all/5dab871f-8f6a-44a7-a495-080e98cd4212-result.json: -------------------------------------------------------------------------------- 1 | {"name": "test_upload_homework_success[test_info2]", "status": "passed", "description": "提交作业成功", "parameters": [{"name": "test_info", "value": "{'file_path': 'F:\\\\课堂派web\\\\files\\\\txt文档.txt', 'expected': '作业提交成功'}"}], "start": 1595077695610, "stop": 1595077699594, "uuid": "68795572-15bc-45c4-86d7-a77f716ed32d", "historyId": "5d630a49200a65b87234047af294a5b2", "testCaseId": "b7b8d14c0311e805effa61e23a4d5200", "fullName": "tests.test_homework.TestHomework#test_upload_homework_success", "labels": [{"name": "tag", "value": "homework"}, {"name": "parentSuite", "value": "tests"}, {"name": "suite", "value": "test_homework"}, {"name": "subSuite", "value": "TestHomework"}, {"name": "host", "value": "DESKTOP-83PFO6C"}, {"name": "thread", "value": "12272-MainThread"}, {"name": "framework", "value": "pytest"}, {"name": "language", "value": "cpython3"}, {"name": "package", "value": "tests.test_homework"}]} -------------------------------------------------------------------------------- /reports/test_all/6245e51f-71c5-47d9-aded-1b8bf8192ac6-attachment.txt: -------------------------------------------------------------------------------- 1 | ERROR  root:base_page.py:32 元素定位失败:Message: no such element: Unable to locate element: {"method":"xpath","selector":"//a[@class="new-tj1"]"} 2 | (Session info: chrome=83.0.4103.116) 3 | (Driver info: chromedriver=71.0.3578.137 (86ee722808adfe9e3c92e6e8ea746ade08423c7e),platform=Windows NT 10.0.18363 x86_64) 4 | 5 | ERROR  root:homework_page.py:56 点击更新提交失败:'NoneType' object has no attribute 'click' 6 | ERROR  root:base_page.py:65 元素定位失败:Message: 7 | 8 | ERROR  root:homework_page.py:73 点击更新提交失败:'NoneType' object has no attribute 'click' -------------------------------------------------------------------------------- /reports/test_all/731bc18c-82f9-4cdf-af9c-f7038d17c9ee-result.json: -------------------------------------------------------------------------------- 1 | {"name": "test_exit_error[test_info0]", "status": "broken", "statusDetails": {"message": "AttributeError: 'NoneType' object has no attribute 'text'", "trace": "self = , test_info = {'expected': '密码错误', 'password': 'zxz'}\njoin_course = \n\n @pytest.mark.error\n @pytest.mark.parametrize(\"test_info\", exit_cases_error)\n def test_exit_error(self, test_info, join_course):\n \"\"\"退课失败\"\"\"\n driver = join_course\n main_page = MainPage(driver)\n> actual = main_page.get().click_more_btn().exit_course(test_info[\"password\"]).get_success_msg()\n\ntests\\test_course.py:60: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\n\nself = \n\n def get_success_msg(self):\n \"\"\"获取成功信息\"\"\"\n e = self.wait_element_visible(self.success_msg_locator)\n> return e.text\nE AttributeError: 'NoneType' object has no attribute 'text'\n\npages\\main_page.py:71: AttributeError"}, "description": "退课失败", "attachments": [{"name": "log", "source": "8be4ce2d-e17b-4a2d-9172-6e42d2bd7b71-attachment.txt", "type": "text/plain"}], "parameters": [{"name": "test_info", "value": "{'password': 'zxz', 'expected': '密码错误'}"}], "start": 1595077597361, "stop": 1595077619243, "uuid": "42baa144-e0ef-4af1-909a-63d52683493b", "historyId": "0760b40c76161342aab7195da7ed70de", "testCaseId": "18a4f4731c8b19040ea89c2e2ccc77fb", "fullName": "tests.test_course.TestCourse#test_exit_error", "labels": [{"name": "tag", "value": "error"}, {"name": "tag", "value": "course"}, {"name": "parentSuite", "value": "tests"}, {"name": "suite", "value": "test_course"}, {"name": "subSuite", "value": "TestCourse"}, {"name": "host", "value": "DESKTOP-83PFO6C"}, {"name": "thread", "value": "12272-MainThread"}, {"name": "framework", "value": "pytest"}, {"name": "language", "value": "cpython3"}, {"name": "package", "value": "tests.test_course"}]} -------------------------------------------------------------------------------- /reports/test_all/7d344dc5-3fe2-4461-8ef5-f00b5535e849-result.json: -------------------------------------------------------------------------------- 1 | {"name": "test_add_success[test_info1]", "status": "passed", "description": "加课失败", "parameters": [{"name": "test_info", "value": "{'course_code': '123456', 'expected': '该加课码不存在或者已经失效'}"}], "start": 1595077595032, "stop": 1595077596019, "uuid": "8e370789-8059-42d0-862e-494ae3f01ba6", "historyId": "b6b1da51b2a8f83df7502cab83f5d8c9", "testCaseId": "c00fc0a16e4502b552e092a5e62abb28", "fullName": "tests.test_course.TestCourse#test_add_success", "labels": [{"name": "tag", "value": "error"}, {"name": "tag", "value": "course"}, {"name": "parentSuite", "value": "tests"}, {"name": "suite", "value": "test_course"}, {"name": "subSuite", "value": "TestCourse"}, {"name": "host", "value": "DESKTOP-83PFO6C"}, {"name": "thread", "value": "12272-MainThread"}, {"name": "framework", "value": "pytest"}, {"name": "language", "value": "cpython3"}, {"name": "package", "value": "tests.test_course"}]} -------------------------------------------------------------------------------- /reports/test_all/7d3c66ed-c6d3-410a-98e2-5f6b085ad8e4-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "444fb3ef-7f1a-4f6f-81a3-dd1b26403787", "befores": [{"name": "test_info", "status": "passed", "start": 1595077703820, "stop": 1595077703820}], "start": 1595077703820, "stop": 1595077707947} -------------------------------------------------------------------------------- /reports/test_all/7dd62fb1-ea9d-4166-81a3-35f5df15977e-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "396e619a-78af-4e2a-9744-e8fdb653c6ef", "children": ["f0298da9-eddf-4624-9c72-91cab5e57fdd", "dc0a2f15-4245-49c2-9011-283adcf7e023", "8e370789-8059-42d0-862e-494ae3f01ba6", "42baa144-e0ef-4af1-909a-63d52683493b"], "befores": [{"name": "browser", "status": "passed", "start": 1595077568266, "stop": 1595077578253}], "afters": [{"name": "browser::0", "status": "passed", "start": 1595077619299, "stop": 1595077621521}], "start": 1595077568266, "stop": 1595077621522} -------------------------------------------------------------------------------- /reports/test_all/80a6a4e8-925c-4f47-b0be-98047105546c-result.json: -------------------------------------------------------------------------------- 1 | {"name": "test_upload_homework_success[test_info1]", "status": "passed", "description": "提交作业成功", "parameters": [{"name": "test_info", "value": "{'file_path': 'F:\\\\课堂派web\\\\files\\\\py代码.py', 'expected': '作业提交成功'}"}], "start": 1595077691867, "stop": 1595077695605, "uuid": "e24c4dda-7f3e-4387-a8f9-5c0e59b1dc40", "historyId": "a2582194ddfcd4f95e370aa89e7568c9", "testCaseId": "b7b8d14c0311e805effa61e23a4d5200", "fullName": "tests.test_homework.TestHomework#test_upload_homework_success", "labels": [{"name": "tag", "value": "homework"}, {"name": "parentSuite", "value": "tests"}, {"name": "suite", "value": "test_homework"}, {"name": "subSuite", "value": "TestHomework"}, {"name": "host", "value": "DESKTOP-83PFO6C"}, {"name": "thread", "value": "12272-MainThread"}, {"name": "framework", "value": "pytest"}, {"name": "language", "value": "cpython3"}, {"name": "package", "value": "tests.test_homework"}]} -------------------------------------------------------------------------------- /reports/test_all/87ba29d5-cc41-4db5-acaa-3fc920da1064-result.json: -------------------------------------------------------------------------------- 1 | {"name": "test_homework_success[test_info1]", "status": "passed", "description": "作业提交、留言、查看提交日志", "parameters": [{"name": "test_info", "value": "{'file_path': 'F:\\\\课堂派web\\\\files\\\\txt文档.txt', 'message': '第2次提交作业!', 'expected1': '作业提交成功', 'expected2': '第2次提交作业!', 'expected3': '添加了 \"txt文档.txt\" 并提交'}"}], "start": 1595077683788, "stop": 1595077688181, "uuid": "1bb6a023-b927-4e51-ae19-7ff6731bbf69", "historyId": "a989d10f2dab02855037b34bd2449ce2", "testCaseId": "5d8362fec30a959c9d73c38f9385d2b3", "fullName": "tests.test_homework.TestHomework#test_homework_success", "labels": [{"name": "tag", "value": "smoke"}, {"name": "tag", "value": "homework"}, {"name": "parentSuite", "value": "tests"}, {"name": "suite", "value": "test_homework"}, {"name": "subSuite", "value": "TestHomework"}, {"name": "host", "value": "DESKTOP-83PFO6C"}, {"name": "thread", "value": "12272-MainThread"}, {"name": "framework", "value": "pytest"}, {"name": "language", "value": "cpython3"}, {"name": "package", "value": "tests.test_homework"}]} -------------------------------------------------------------------------------- /reports/test_all/88eac872-f27f-432c-b448-4801fc9b359c-result.json: -------------------------------------------------------------------------------- 1 | {"name": "test_homework_success[test_info0]", "status": "passed", "description": "作业提交、留言、查看提交日志", "attachments": [{"name": "log", "source": "6245e51f-71c5-47d9-aded-1b8bf8192ac6-attachment.txt", "type": "text/plain"}], "parameters": [{"name": "test_info", "value": "{'file_path': 'F:\\\\课堂派web\\\\files\\\\txt文档.txt', 'message': '第1次提交作业!', 'expected1': '作业提交成功', 'expected2': '第1次提交作业!', 'expected3': '添加了 \"txt文档.txt\" 并提交'}"}], "start": 1595077638701, "stop": 1595077683759, "uuid": "ea51762e-f2e5-40d2-a2e6-35ab54db5598", "historyId": "583fb3aa4a60427cc8b811c26e2bcd4d", "testCaseId": "5d8362fec30a959c9d73c38f9385d2b3", "fullName": "tests.test_homework.TestHomework#test_homework_success", "labels": [{"name": "tag", "value": "smoke"}, {"name": "tag", "value": "homework"}, {"name": "parentSuite", "value": "tests"}, {"name": "suite", "value": "test_homework"}, {"name": "subSuite", "value": "TestHomework"}, {"name": "host", "value": "DESKTOP-83PFO6C"}, {"name": "thread", "value": "12272-MainThread"}, {"name": "framework", "value": "pytest"}, {"name": "language", "value": "cpython3"}, {"name": "package", "value": "tests.test_homework"}]} -------------------------------------------------------------------------------- /reports/test_all/8b104685-b739-4305-ac21-4a41cbcdb50b-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "8ae14f82-1717-442a-9c38-e94ad48dcca9", "befores": [{"name": "test_info", "status": "passed", "start": 1595077769840, "stop": 1595077769840}], "start": 1595077769840, "stop": 1595077772076} -------------------------------------------------------------------------------- /reports/test_all/8be4ce2d-e17b-4a2d-9172-6e42d2bd7b71-attachment.txt: -------------------------------------------------------------------------------- 1 | ERROR  root:base_page.py:76 元素定位失败:Message: -------------------------------------------------------------------------------- /reports/test_all/96e5a1f1-3de1-47ca-bd11-41837f87eefa-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "e681f17b-16f7-45de-a616-994ef7dc85b9", "befores": [{"name": "test_info", "status": "passed", "start": 1595077699610, "stop": 1595077699610}], "start": 1595077699610, "stop": 1595077703815} -------------------------------------------------------------------------------- /reports/test_all/97a1c9fb-596c-4c97-859b-9efd965d1d3a-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "793b88f9-42f7-46f5-bc17-0ce0a5ca3b37", "befores": [{"name": "test_info", "status": "passed", "start": 1595077688187, "stop": 1595077688187}], "start": 1595077688187, "stop": 1595077691848} -------------------------------------------------------------------------------- /reports/test_all/98a7374f-0743-4b64-8a48-270f75841269-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "f4d972e0-6884-42c9-a454-764c4fcb6131", "befores": [{"name": "test_info", "status": "passed", "start": 1595077595031, "stop": 1595077595031}], "start": 1595077595031, "stop": 1595077596022} -------------------------------------------------------------------------------- /reports/test_all/a2560e91-4446-4b68-8309-56f4167fae61-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "959d1bc7-a00b-42b6-8ab4-b06e123e1394", "befores": [{"name": "test_info", "status": "passed", "start": 1595077695610, "stop": 1595077695610}], "start": 1595077695610, "stop": 1595077699596} -------------------------------------------------------------------------------- /reports/test_all/a2feab51-69ef-403f-bf3d-eb8aa67ebca7-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "2738e0d4-f0f2-46d3-9a69-31ce9ab4acfc", "children": ["42baa144-e0ef-4af1-909a-63d52683493b"], "befores": [{"name": "join_course", "status": "passed", "start": 1595077596027, "stop": 1595077597360}], "afters": [{"name": "join_course::0", "status": "passed", "start": 1595077619297, "stop": 1595077619297}], "start": 1595077596027, "stop": 1595077619297} -------------------------------------------------------------------------------- /reports/test_all/a766fb96-fc50-410c-aab0-adf4d4f712d2-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "e9e6f0bf-637f-427d-97ec-6af184a64cac", "befores": [{"name": "test_info", "status": "passed", "start": 1595077720054, "stop": 1595077720054}], "start": 1595077720054, "stop": 1595077724517} -------------------------------------------------------------------------------- /reports/test_all/a8c4fdf1-b2a6-4c58-984c-e6d9ae1e2374-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "d0eb8e0f-ee52-402a-8b46-da5348f449c8", "children": ["896f02b0-d0a1-4a08-ab9d-ea5f6849e4d7", "639f7cd3-d049-44f4-9f55-dfd0ea12351f"], "befores": [{"name": "enter_students_page", "status": "passed", "start": 1595077764908, "stop": 1595077767488}], "afters": [{"name": "enter_students_page::0", "status": "passed", "start": 1595077772078, "stop": 1595077772078}], "start": 1595077764908, "stop": 1595077772078} -------------------------------------------------------------------------------- /reports/test_all/af02b8b7-3925-4678-b8ff-84936ea22b8e-result.json: -------------------------------------------------------------------------------- 1 | {"name": "test_join_exit_success[test_info0]", "status": "passed", "description": "加课、进入课堂、退课成功", "parameters": [{"name": "test_info", "value": "{'course_code': 'P69UVV', 'password': 'python123', 'expected1': '加入课堂成功', 'expected2': 'P69UVV', 'expected3': '课程退课成功'}"}], "start": 1595077590801, "stop": 1595077594097, "uuid": "f0298da9-eddf-4624-9c72-91cab5e57fdd", "historyId": "347704dc05aa29a914668ff065822f00", "testCaseId": "5898bea2e4b94ab668508e6565b55dda", "fullName": "tests.test_course.TestCourse#test_join_exit_success", "labels": [{"name": "tag", "value": "success"}, {"name": "tag", "value": "course"}, {"name": "tag", "value": "smoke"}, {"name": "parentSuite", "value": "tests"}, {"name": "suite", "value": "test_course"}, {"name": "subSuite", "value": "TestCourse"}, {"name": "host", "value": "DESKTOP-83PFO6C"}, {"name": "thread", "value": "12272-MainThread"}, {"name": "framework", "value": "pytest"}, {"name": "language", "value": "cpython3"}, {"name": "package", "value": "tests.test_course"}]} -------------------------------------------------------------------------------- /reports/test_all/b70d737e-1d07-4dd1-84f8-53dbe040fc6e-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "bb07a8f0-6da6-463d-87f5-ec7c7498afb7", "befores": [{"name": "test_info", "status": "passed", "start": 1595077594125, "stop": 1595077594125}], "start": 1595077594124, "stop": 1595077595026} -------------------------------------------------------------------------------- /reports/test_all/c052b6bb-ec2b-42fc-a4f7-e3d587d56402-result.json: -------------------------------------------------------------------------------- 1 | {"name": "test_upload_homework_success[test_info4]", "status": "passed", "description": "提交作业成功", "parameters": [{"name": "test_info", "value": "{'file_path': 'F:\\\\课堂派web\\\\files\\\\压缩包.rar', 'expected': '作业提交成功'}"}], "start": 1595077703821, "stop": 1595077707947, "uuid": "dcac2979-e430-4e54-9499-2d2a4db741bf", "historyId": "cb4a604396164559b6ee7f8b94b3b41e", "testCaseId": "b7b8d14c0311e805effa61e23a4d5200", "fullName": "tests.test_homework.TestHomework#test_upload_homework_success", "labels": [{"name": "tag", "value": "homework"}, {"name": "parentSuite", "value": "tests"}, {"name": "suite", "value": "test_homework"}, {"name": "subSuite", "value": "TestHomework"}, {"name": "host", "value": "DESKTOP-83PFO6C"}, {"name": "thread", "value": "12272-MainThread"}, {"name": "framework", "value": "pytest"}, {"name": "language", "value": "cpython3"}, {"name": "package", "value": "tests.test_homework"}]} -------------------------------------------------------------------------------- /reports/test_all/c3c996d7-2e8d-4b96-aa1e-2a941c568ac5-result.json: -------------------------------------------------------------------------------- 1 | {"name": "test_login_error[test_info0]", "status": "passed", "description": "登录失败", "parameters": [{"name": "test_info", "value": "{'mobile': '', 'password': '12', 'expected': '账号不能为空'}"}], "start": 1595077724521, "stop": 1595077730220, "uuid": "01cf2a92-e652-4900-bbf6-c8aea2c6c57c", "historyId": "1a42a92fe9250ffdeb64eef1609dd764", "testCaseId": "5fd5da3b3ca8fdf751feb802572e5b42", "fullName": "tests.test_login.TestLogin#test_login_error", "labels": [{"name": "tag", "value": "login"}, {"name": "parentSuite", "value": "tests"}, {"name": "suite", "value": "test_login"}, {"name": "subSuite", "value": "TestLogin"}, {"name": "host", "value": "DESKTOP-83PFO6C"}, {"name": "thread", "value": "12272-MainThread"}, {"name": "framework", "value": "pytest"}, {"name": "language", "value": "cpython3"}, {"name": "package", "value": "tests.test_login"}]} -------------------------------------------------------------------------------- /reports/test_all/d215575b-67d6-44c8-a840-258aa2b41e2f-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "5776bb8e-5bcf-44ba-8905-601f70af52ce", "children": ["896f02b0-d0a1-4a08-ab9d-ea5f6849e4d7", "639f7cd3-d049-44f4-9f55-dfd0ea12351f"], "befores": [{"name": "login_page", "status": "passed", "start": 1595077759509, "stop": 1595077762211}], "afters": [{"name": "login_page::0", "status": "passed", "start": 1595077772105, "stop": 1595077772105}], "start": 1595077759509, "stop": 1595077772105} -------------------------------------------------------------------------------- /reports/test_all/d29659e4-f8bc-49a1-bd41-236b80755237-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "da1b567e-70dd-4402-8971-35e25d1c5abb", "children": ["ea51762e-f2e5-40d2-a2e6-35ab54db5598", "1bb6a023-b927-4e51-ae19-7ff6731bbf69", "c9ca5fc2-fa58-407b-bc6b-88d7dc279774", "e24c4dda-7f3e-4387-a8f9-5c0e59b1dc40", "68795572-15bc-45c4-86d7-a77f716ed32d", "a2e559fa-de7c-45fd-898a-86a80b706e2c", "dcac2979-e430-4e54-9499-2d2a4db741bf"], "befores": [{"name": "login_page", "status": "passed", "start": 1595077631149, "stop": 1595077633511}], "afters": [{"name": "login_page::0", "status": "passed", "start": 1595077707995, "stop": 1595077707995}], "start": 1595077631149, "stop": 1595077707995} -------------------------------------------------------------------------------- /reports/test_all/d30c37dd-47fc-4292-83a0-8693c7ae83df-result.json: -------------------------------------------------------------------------------- 1 | {"name": "test_upload_homework_success[test_info3]", "status": "passed", "description": "提交作业成功", "parameters": [{"name": "test_info", "value": "{'file_path': 'F:\\\\课堂派web\\\\files\\\\xlsx文件.xlsx', 'expected': '作业提交成功'}"}], "start": 1595077699611, "stop": 1595077703814, "uuid": "a2e559fa-de7c-45fd-898a-86a80b706e2c", "historyId": "4d4a6d3df4a82825e8c2060e70a83f3b", "testCaseId": "b7b8d14c0311e805effa61e23a4d5200", "fullName": "tests.test_homework.TestHomework#test_upload_homework_success", "labels": [{"name": "tag", "value": "homework"}, {"name": "parentSuite", "value": "tests"}, {"name": "suite", "value": "test_homework"}, {"name": "subSuite", "value": "TestHomework"}, {"name": "host", "value": "DESKTOP-83PFO6C"}, {"name": "thread", "value": "12272-MainThread"}, {"name": "framework", "value": "pytest"}, {"name": "language", "value": "cpython3"}, {"name": "package", "value": "tests.test_homework"}]} -------------------------------------------------------------------------------- /reports/test_all/d72e7d59-5f8b-458a-9f1d-d487eeb91524-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "6956be1e-fed6-44f1-88d9-0e6aa6c14c30", "children": ["ea51762e-f2e5-40d2-a2e6-35ab54db5598", "1bb6a023-b927-4e51-ae19-7ff6731bbf69", "c9ca5fc2-fa58-407b-bc6b-88d7dc279774", "e24c4dda-7f3e-4387-a8f9-5c0e59b1dc40", "68795572-15bc-45c4-86d7-a77f716ed32d", "a2e559fa-de7c-45fd-898a-86a80b706e2c", "dcac2979-e430-4e54-9499-2d2a4db741bf"], "befores": [{"name": "enter_homework_page", "status": "passed", "start": 1595077635610, "stop": 1595077638700}], "afters": [{"name": "enter_homework_page::0", "status": "passed", "start": 1595077707987, "stop": 1595077707987}], "start": 1595077635610, "stop": 1595077707987} -------------------------------------------------------------------------------- /reports/test_all/d917c678-9900-40af-ab75-49a7640ec461-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "2b589d3b-0bca-44bb-9976-711c10667063", "befores": [{"name": "test_info", "status": "passed", "start": 1595077597360, "stop": 1595077597360}], "start": 1595077597360, "stop": 1595077619296} -------------------------------------------------------------------------------- /reports/test_all/dc12eccf-22de-4b43-906a-ad44172689bc-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "e178f723-d45c-438c-91ad-64589bfa0e88", "children": ["896f02b0-d0a1-4a08-ab9d-ea5f6849e4d7", "639f7cd3-d049-44f4-9f55-dfd0ea12351f"], "befores": [{"name": "join_course", "status": "passed", "start": 1595077762211, "stop": 1595077764908}], "afters": [{"name": "join_course::0", "status": "passed", "start": 1595077772104, "stop": 1595077772104}], "start": 1595077762211, "stop": 1595077772104} -------------------------------------------------------------------------------- /reports/test_all/df29e220-83bc-47b4-aa0b-bfbc96077006-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "9c80426a-fd39-4797-9d28-b323b2e3b65d", "children": ["ea51762e-f2e5-40d2-a2e6-35ab54db5598", "1bb6a023-b927-4e51-ae19-7ff6731bbf69", "c9ca5fc2-fa58-407b-bc6b-88d7dc279774", "e24c4dda-7f3e-4387-a8f9-5c0e59b1dc40", "68795572-15bc-45c4-86d7-a77f716ed32d", "a2e559fa-de7c-45fd-898a-86a80b706e2c", "dcac2979-e430-4e54-9499-2d2a4db741bf"], "befores": [{"name": "browser", "status": "passed", "start": 1595077621595, "stop": 1595077631149}], "afters": [{"name": "browser::0", "status": "passed", "start": 1595077707999, "stop": 1595077710213}], "start": 1595077621595, "stop": 1595077710213} -------------------------------------------------------------------------------- /reports/test_all/ed43be7e-c3b9-412f-adb6-9766de61b7b7-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "56bdac0d-31b2-4733-b1f9-039e51815c58", "befores": [{"name": "test_info", "status": "passed", "start": 1595077691867, "stop": 1595077691867}], "start": 1595077691867, "stop": 1595077695606} -------------------------------------------------------------------------------- /reports/test_all/ed6b337e-588f-4215-8048-b2b656eadd14-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "d7a28f16-ea01-4fef-bdf4-49a0ba3344ea", "befores": [{"name": "test_info", "status": "passed", "start": 1595077767489, "stop": 1595077767489}], "start": 1595077767489, "stop": 1595077769837} -------------------------------------------------------------------------------- /reports/test_course.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Test Report 6 | 7 | 8 | 245 |

test_course.html

246 |

Report generated on 18-Jul-2020 at 20:10:04 by pytest-html v2.1.1

247 |

Environment

248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 |
JAVA_HOMED:\Java\jdk1.8.0_231
Packages{"pluggy": "0.13.1", "py": "1.8.1", "pytest": "5.4.3"}
PlatformWindows-10-10.0.18362-SP0
Plugins{"allure-pytest": "2.8.16", "html": "2.1.1", "metadata": "1.9.0", "rerunfailures": "9.0"}
Python3.7.3
264 |

Summary

265 |

4 tests ran in 43.66 seconds.

266 | 3 passed, 0 skipped, 1 failed, 0 errors, 0 expected failures, 0 unexpected passes, 0 rerun 267 |

Results

268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 |
ResultTestDurationLinks
Failedtests/test_course.py::TestCourse::test_exit_error[test_info0]20.95
285 |
self = <test_course.TestCourse object at 0x000001B01E86B1D0>
test_info = {'expected': '密码错误', 'password': 'zxz'}
join_course = <selenium.webdriver.chrome.webdriver.WebDriver (session="b3fbd3f12579d19c2e8d654d896feedc")>

@pytest.mark.error
@pytest.mark.parametrize("test_info", exit_cases_error)
def test_exit_error(self, test_info, join_course):
"""退课失败"""
driver = join_course
main_page = MainPage(driver)
> main_page = main_page.get().exit_course(test_info["password"])

tests\test_course.py:60:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
pages\main_page.py:83: in exit_course
e1.click()
D:\Python3.7\lib\site-packages\selenium\webdriver\remote\webelement.py:80: in click
self._execute(Command.CLICK_ELEMENT)
D:\Python3.7\lib\site-packages\selenium\webdriver\remote\webelement.py:633: in _execute
return self._parent.execute(command, params)
D:\Python3.7\lib\site-packages\selenium\webdriver\remote\webdriver.py:321: in execute
self.error_handler.check_response(response)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <selenium.webdriver.remote.errorhandler.ErrorHandler object at 0x000001B01DB5C5F8>
response = {'sessionId': 'b3fbd3f12579d19c2e8d654d896feedc', 'status': 11, 'value': {'message': 'element not interactable\n (Ses...r info: chromedriver=71.0.3578.137 (86ee722808adfe9e3c92e6e8ea746ade08423c7e),platform=Windows NT 10.0.18363 x86_64)'}}

def check_response(self, response):
"""
Checks that a JSON response from the WebDriver does not have an error.

:Args:
- response - The JSON response from the WebDriver server as a dictionary
object.

:Raises: If the response contains an error message.
"""
status = response.get('status', None)
if status is None or status == ErrorCode.SUCCESS:
return
value = None
message = response.get("message", "")
screen = response.get("screen", "")
stacktrace = None
if isinstance(status, int):
value_json = response.get('value', None)
if value_json and isinstance(value_json, basestring):
import json
try:
value = json.loads(value_json)
if len(value.keys()) == 1:
value = value['value']
status = value.get('error', None)
if status is None:
status = value["status"]
message = value["value"]
if not isinstance(message, basestring):
value = message
message = message.get('message')
else:
message = value.get('message', None)
except ValueError:
pass

exception_class = ErrorInResponseException
if status in ErrorCode.NO_SUCH_ELEMENT:
exception_class = NoSuchElementException
elif status in ErrorCode.NO_SUCH_FRAME:
exception_class = NoSuchFrameException
elif status in ErrorCode.NO_SUCH_WINDOW:
exception_class = NoSuchWindowException
elif status in ErrorCode.STALE_ELEMENT_REFERENCE:
exception_class = StaleElementReferenceException
elif status in ErrorCode.ELEMENT_NOT_VISIBLE:
exception_class = ElementNotVisibleException
elif status in ErrorCode.INVALID_ELEMENT_STATE:
exception_class = InvalidElementStateException
elif status in ErrorCode.INVALID_SELECTOR \
or status in ErrorCode.INVALID_XPATH_SELECTOR \
or status in ErrorCode.INVALID_XPATH_SELECTOR_RETURN_TYPER:
exception_class = InvalidSelectorException
elif status in ErrorCode.ELEMENT_IS_NOT_SELECTABLE:
exception_class = ElementNotSelectableException
elif status in ErrorCode.ELEMENT_NOT_INTERACTABLE:
exception_class = ElementNotInteractableException
elif status in ErrorCode.INVALID_COOKIE_DOMAIN:
exception_class = InvalidCookieDomainException
elif status in ErrorCode.UNABLE_TO_SET_COOKIE:
exception_class = UnableToSetCookieException
elif status in ErrorCode.TIMEOUT:
exception_class = TimeoutException
elif status in ErrorCode.SCRIPT_TIMEOUT:
exception_class = TimeoutException
elif status in ErrorCode.UNKNOWN_ERROR:
exception_class = WebDriverException
elif status in ErrorCode.UNEXPECTED_ALERT_OPEN:
exception_class = UnexpectedAlertPresentException
elif status in ErrorCode.NO_ALERT_OPEN:
exception_class = NoAlertPresentException
elif status in ErrorCode.IME_NOT_AVAILABLE:
exception_class = ImeNotAvailableException
elif status in ErrorCode.IME_ENGINE_ACTIVATION_FAILED:
exception_class = ImeActivationFailedException
elif status in ErrorCode.MOVE_TARGET_OUT_OF_BOUNDS:
exception_class = MoveTargetOutOfBoundsException
elif status in ErrorCode.JAVASCRIPT_ERROR:
exception_class = JavascriptException
elif status in ErrorCode.SESSION_NOT_CREATED:
exception_class = SessionNotCreatedException
elif status in ErrorCode.INVALID_ARGUMENT:
exception_class = InvalidArgumentException
elif status in ErrorCode.NO_SUCH_COOKIE:
exception_class = NoSuchCookieException
elif status in ErrorCode.UNABLE_TO_CAPTURE_SCREEN:
exception_class = ScreenshotException
elif status in ErrorCode.ELEMENT_CLICK_INTERCEPTED:
exception_class = ElementClickInterceptedException
elif status in ErrorCode.INSECURE_CERTIFICATE:
exception_class = InsecureCertificateException
elif status in ErrorCode.INVALID_COORDINATES:
exception_class = InvalidCoordinatesException
elif status in ErrorCode.INVALID_SESSION_ID:
exception_class = InvalidSessionIdException
elif status in ErrorCode.UNKNOWN_METHOD:
exception_class = UnknownMethodException
else:
exception_class = WebDriverException
if value == '' or value is None:
value = response['value']
if isinstance(value, basestring):
if exception_class == ErrorInResponseException:
raise exception_class(response, value)
raise exception_class(value)
if message == "" and 'message' in value:
message = value['message']

screen = None
if 'screen' in value:
screen = value['screen']

stacktrace = None
if 'stackTrace' in value and value['stackTrace']:
stacktrace = []
try:
for frame in value['stackTrace']:
line = self._value_or_default(frame, 'lineNumber', '')
file = self._value_or_default(frame, 'fileName', '<anonymous>')
if line:
file = "%s:%s" % (file, line)
meth = self._value_or_default(frame, 'methodName', '<anonymous>')
if 'className' in frame:
meth = "%s.%s" % (frame['className'], meth)
msg = " at %s (%s)"
msg = msg % (meth, file)
stacktrace.append(msg)
except TypeError:
pass
if exception_class == ErrorInResponseException:
raise exception_class(response, message)
elif exception_class == UnexpectedAlertPresentException:
alert_text = None
if 'data' in value:
alert_text = value['data'].get('text')
elif 'alert' in value:
alert_text = value['alert'].get('text')
raise exception_class(message, screen, stacktrace, alert_text)
> raise exception_class(message, screen, stacktrace)
E selenium.common.exceptions.ElementNotVisibleException: Message: element not interactable
E (Session info: chrome=83.0.4103.116)
E (Driver info: chromedriver=71.0.3578.137 (86ee722808adfe9e3c92e6e8ea746ade08423c7e),platform=Windows NT 10.0.18363 x86_64)

D:\Python3.7\lib\site-packages\selenium\webdriver\remote\errorhandler.py:242: ElementNotVisibleException
Passedtests/test_course.py::TestCourse::test_join_exit_success[test_info0]4.02
294 |
No log output captured.
Passedtests/test_course.py::TestCourse::test_add_success[test_info0]0.94
303 |
No log output captured.
Passedtests/test_course.py::TestCourse::test_add_success[test_info1]1.18
312 |
No log output captured.
-------------------------------------------------------------------------------- /reports/test_homework.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Test Report 6 | 7 | 8 | 245 |

test_homework.html

246 |

Report generated on 18-Jul-2020 at 20:37:40 by pytest-html v2.1.1

247 |

Environment

248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 |
JAVA_HOMED:\Java\jdk1.8.0_231
Packages{"pluggy": "0.13.1", "py": "1.8.1", "pytest": "5.4.3"}
PlatformWindows-10-10.0.18362-SP0
Plugins{"allure-pytest": "2.8.16", "html": "2.1.1", "metadata": "1.9.0", "rerunfailures": "9.0"}
Python3.7.3
264 |

Summary

265 |

7 tests ran in 52.56 seconds.

266 | 7 passed, 0 skipped, 0 failed, 0 errors, 0 expected failures, 0 unexpected passes, 0 rerun 267 |

Results

268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 |
ResultTestDurationLinks
Passedtests/test_homework.py::TestHomework::test_homework_success[test_info0]4.92
285 |
No log output captured.
Passedtests/test_homework.py::TestHomework::test_homework_success[test_info1]4.59
294 |
No log output captured.
Passedtests/test_homework.py::TestHomework::test_upload_homework_success[test_info0]3.95
303 |
No log output captured.
Passedtests/test_homework.py::TestHomework::test_upload_homework_success[test_info1]4.26
312 |
No log output captured.
Passedtests/test_homework.py::TestHomework::test_upload_homework_success[test_info2]4.45
321 |
No log output captured.
Passedtests/test_homework.py::TestHomework::test_upload_homework_success[test_info3]4.35
330 |
No log output captured.
Passedtests/test_homework.py::TestHomework::test_upload_homework_success[test_info4]4.57
339 |
No log output captured.
-------------------------------------------------------------------------------- /reports/test_login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Test Report 6 | 7 | 8 | 245 |

test_smoe.html

246 |

Report generated on 18-Jul-2020 at 19:47:14 by pytest-html v2.1.1

247 |

Environment

248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 |
JAVA_HOMED:\Java\jdk1.8.0_231
Packages{"pluggy": "0.13.1", "py": "1.8.1", "pytest": "5.4.3"}
PlatformWindows-10-10.0.18362-SP0
Plugins{"allure-pytest": "2.8.16", "html": "2.1.1", "metadata": "1.9.0", "rerunfailures": "9.0"}
Python3.7.3
264 |

Summary

265 |

5 tests ran in 18.14 seconds.

266 | 5 passed, 0 skipped, 0 failed, 0 errors, 0 expected failures, 0 unexpected passes, 0 rerun 267 |

Results

268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 |
ResultTestDurationLinks
Passedtests/test_login.py::TestLogin::test_login_success[test_info0]3.64
285 |
No log output captured.
Passedtests/test_login.py::TestLogin::test_login_error[test_info0]0.59
294 |
No log output captured.
Passedtests/test_login.py::TestLogin::test_login_error[test_info1]0.52
303 |
No log output captured.
Passedtests/test_login.py::TestLogin::test_login_error[test_info2]0.69
312 |
No log output captured.
Passedtests/test_login.py::TestLogin::test_login_error[test_info3]0.73
321 |
No log output captured.
-------------------------------------------------------------------------------- /reports/test_message.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Test Report 6 | 7 | 8 | 245 |

test_message.html

246 |

Report generated on 18-Jul-2020 at 19:52:43 by pytest-html v2.1.1

247 |

Environment

248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 |
JAVA_HOMED:\Java\jdk1.8.0_231
Packages{"pluggy": "0.13.1", "py": "1.8.1", "pytest": "5.4.3"}
PlatformWindows-10-10.0.18362-SP0
Plugins{"allure-pytest": "2.8.16", "html": "2.1.1", "metadata": "1.9.0", "rerunfailures": "9.0"}
Python3.7.3
264 |

Summary

265 |

2 tests ran in 22.76 seconds.

266 | 2 passed, 0 skipped, 0 failed, 0 errors, 0 expected failures, 0 unexpected passes, 0 rerun 267 |

Results

268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 |
ResultTestDurationLinks
Passedtests/test_message.py::TestSendMessage::test_send_message_success[test_info0]2.25
285 |
No log output captured.
Passedtests/test_message.py::TestSendMessage::test_send_message_success[test_info1]1.97
294 |
No log output captured.
-------------------------------------------------------------------------------- /reports/test_smoke.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Test Report 6 | 7 | 8 | 245 |

test_smoke.html

246 |

Report generated on 18-Jul-2020 at 20:41:40 by pytest-html v2.1.1

247 |

Environment

248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 |
JAVA_HOMED:\Java\jdk1.8.0_231
Packages{"pluggy": "0.13.1", "py": "1.8.1", "pytest": "5.4.3"}
PlatformWindows-10-10.0.18362-SP0
Plugins{"allure-pytest": "2.8.16", "html": "2.1.1", "metadata": "1.9.0", "rerunfailures": "9.0"}
Python3.7.3
264 |

Summary

265 |

6 tests ran in 95.92 seconds.

266 | 6 passed, 0 skipped, 0 failed, 0 errors, 0 expected failures, 0 unexpected passes, 0 rerun 267 |

Results

268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 |
ResultTestDurationLinks
Passedtests/test_course.py::TestCourse::test_join_exit_success[test_info0]3.19
285 |
No log output captured.
Passedtests/test_homework.py::TestHomework::test_homework_success[test_info0]4.44
294 |
No log output captured.
Passedtests/test_homework.py::TestHomework::test_homework_success[test_info1]4.31
303 |
No log output captured.
Passedtests/test_login.py::TestLogin::test_login_success[test_info0]13.96
312 |
No log output captured.
Passedtests/test_message.py::TestSendMessage::test_send_message_success[test_info0]2.24
321 |
No log output captured.
Passedtests/test_message.py::TestSendMessage::test_send_message_success[test_info1]1.95
330 |
No log output captured.
-------------------------------------------------------------------------------- /run.py: -------------------------------------------------------------------------------- 1 | """ 2 | 收集和运行用例 3 | """ 4 | 5 | import os 6 | import pytest 7 | from config.config import REPORTS_PATH 8 | 9 | REPORT_FILE = os.path.join(REPORTS_PATH, "test_all") 10 | 11 | if __name__ == '__main__': 12 | # pytest.main(["-m smoke", f"--html={REPORT_FILE}"]) 13 | # pytest.main([f"--html={REPORT_FILE}"]) 14 | # pytest.main(['--alluredir=reports/', "-m", "success"]) 15 | pytest.main([f'--alluredir={REPORT_FILE}']) 16 | # 命令行allure运行 17 | # pytest - -alluredir = reports\test_all 18 | # 查看sllure报告 19 | # allure serve reports\test_all -------------------------------------------------------------------------------- /tests/test_course.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from data.course_data import cases_success, join_cases_success, join_cases_error, exit_cases_error 3 | from pages.main_page import MainPage 4 | 5 | 6 | @pytest.mark.course 7 | class TestCourse: 8 | @pytest.mark.smoke 9 | @pytest.mark.success 10 | @pytest.mark.parametrize("test_info", cases_success) 11 | def test_join_exit_success(self, test_info, login_page): 12 | """加课、进入课堂、退课成功""" 13 | driver = login_page 14 | main_page = MainPage(driver) 15 | join_actual = main_page.get().input_class_code(test_info["course_code"]). \ 16 | sure_join_course().get_success_msg() 17 | # class_page = main_page.enter_class() 18 | # code_actual = class_page.get_course_code() 19 | # main_page = class_page.click_class_btn() 20 | exit_actual = main_page.get().click_more_btn().exit_course(test_info["password"]).get_success_msg() 21 | try: 22 | assert join_actual == test_info["expected1"], "加课成功" 23 | # assert code_actual == test_info["expected2"], "进入课堂成功" 24 | assert exit_actual == test_info["expected3"], "退课成功" 25 | except AssertionError as e: 26 | raise e 27 | 28 | @pytest.mark.success 29 | @pytest.mark.parametrize("test_info", join_cases_success) 30 | def test_add_success(self, test_info, login_page): 31 | """加课成功""" 32 | driver = login_page 33 | main_page = MainPage(driver) 34 | actual = main_page.get().input_class_code(test_info["course_code"]). \ 35 | sure_join_course().get_success_msg() 36 | try: 37 | assert actual == test_info["expected"], "加课成功" 38 | except AssertionError as e: 39 | raise e 40 | 41 | @pytest.mark.error 42 | @pytest.mark.parametrize("test_info", join_cases_error) 43 | def test_add_success(self, test_info, login_page): 44 | """加课失败""" 45 | driver = login_page 46 | main_page = MainPage(driver) 47 | actual = main_page.get().input_class_code(test_info["course_code"]). \ 48 | sure_join_course().get_error_msg() 49 | try: 50 | assert actual == test_info["expected"], "加课失败" 51 | except AssertionError as e: 52 | raise e 53 | 54 | @pytest.mark.error 55 | @pytest.mark.parametrize("test_info", exit_cases_error) 56 | def test_exit_error(self, test_info, join_course): 57 | """退课失败""" 58 | driver = join_course 59 | main_page = MainPage(driver) 60 | actual = main_page.get().click_more_btn().exit_course(test_info["password"]).get_error_msg() 61 | try: 62 | assert actual == test_info["expected"], "退课失败" 63 | except AssertionError as e: 64 | raise e 65 | -------------------------------------------------------------------------------- /tests/test_homework.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from pages.homework_page import HomeWorkPage 3 | from data.homework_data import cases_success, file_cases_success 4 | import logging 5 | 6 | 7 | @pytest.mark.homework 8 | class TestHomework: 9 | """测试Homework页面的上传作业,作业留言,查看作业提交状态: 10 | 前置条件:进入homework页面 11 | 1.上传作业 12 | 2.留言 13 | 3.查看提交日志 14 | """ 15 | @pytest.mark.smoke 16 | @pytest.mark.homework 17 | @pytest.mark.parametrize("test_info", cases_success) 18 | def test_homework_success(self, test_info, enter_homework_page): 19 | """作业提交、留言、查看提交日志""" 20 | driver = enter_homework_page 21 | homework_page = HomeWorkPage(driver) 22 | homework_page.get().upload_files(test_info["file_path"]).comment(test_info["message"]).click_submit_files() 23 | 24 | file_actual = homework_page.get_success_message() 25 | comment_actual = homework_page.click_known().get_comment() 26 | log_actual = homework_page.view_status() 27 | try: 28 | assert file_actual == test_info["expected1"], "作业提交成功" 29 | assert comment_actual == test_info["expected2"], "作业留言成功" 30 | assert test_info["expected3"] in log_actual, "查看作业提交日志成功" 31 | except AssertionError as e: 32 | raise e 33 | 34 | @pytest.mark.homework 35 | @pytest.mark.parametrize("test_info", file_cases_success) 36 | def test_upload_homework_success(self, test_info, enter_homework_page): 37 | """提交作业成功""" 38 | driver = enter_homework_page 39 | homework_page = HomeWorkPage(driver) 40 | homework_page.get().upload_files(test_info["file_path"]) 41 | homework_page.click_submit_files() 42 | file_actual = homework_page.get_success_message() 43 | try: 44 | assert file_actual == test_info["expected"], "作业提交成功" 45 | except AssertionError as e: 46 | raise e 47 | 48 | -------------------------------------------------------------------------------- /tests/test_login.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from pages.login_page import LoginPage 3 | from pages.main_page import MainPage 4 | from data.login_data import cases_error, cases_success 5 | 6 | 7 | @pytest.mark.login 8 | class TestLogin: 9 | @pytest.mark.smoke 10 | @pytest.mark.success 11 | @pytest.mark.parametrize("test_info", cases_success) 12 | def test_login_success(self, test_info, browser): 13 | """登录成功""" 14 | login_page = LoginPage(browser) 15 | login_page.get().login(test_info['mobile'], test_info['password']) 16 | user_info = MainPage(browser).get_user_account() 17 | try: 18 | assert test_info["expected"] in user_info, "登录成功" 19 | except AssertionError as e: 20 | raise e 21 | 22 | @pytest.mark.parametrize("test_info", cases_error) 23 | def test_login_error(self, test_info, browser): 24 | """登录失败""" 25 | login_page = LoginPage(browser) 26 | login_page.get().login(test_info["mobile"], test_info["password"]) 27 | error_msg = login_page.get_error_msg() 28 | try: 29 | assert test_info["expected"] == error_msg, "登录失败" 30 | except AssertionError as e: 31 | raise e 32 | 33 | -------------------------------------------------------------------------------- /tests/test_message.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from pages.students_page import StudentsPage 3 | from data.send_message_data import cases_success 4 | 5 | 6 | @pytest.mark.message 7 | class TestSendMessage: 8 | """测试Students页面的同学私信功能: 9 | 前置条件:进入students页面 10 | 1.发送私信 11 | 2.断言 12 | """ 13 | @pytest.mark.smoke 14 | @pytest.mark.success 15 | @pytest.mark.parametrize("test_info", cases_success) 16 | def test_send_message_success(self, test_info, enter_students_page): 17 | driver = enter_students_page 18 | student_page = StudentsPage(driver) 19 | actual = student_page.get().send_message(test_info["message"]) 20 | try: 21 | assert actual in test_info["expected"], "留言成功" 22 | except AssertionError as e: 23 | raise e 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /课堂派web测试用例.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/donghe123178/web_automation_testing/1be5590eb4fe30055240506ebc7231d3cc457634/课堂派web测试用例.xlsx -------------------------------------------------------------------------------- /课堂派项目介绍.md: -------------------------------------------------------------------------------- 1 | ## 课堂派web自动化项目 2 | 3 | 基于python+pytest+Selenium+allure,完成web自动化测试框架的搭建,并可以在jenkins上持续集成,应用于课堂派web自动化测试项目中,取得良好效果 4 | 5 | #### 一、自动化测试流程: 6 | 7 | 1. 需求分析 8 | 2. 挑选适合做自动化测试的功能 9 | 3. 设计测试用例 10 | 4. 搭建自动化测试环境 11 | 5. 设计自动化测试项目的架构 12 | 6. 编写代码 13 | 7. 执行测试用例 14 | 8. 生成测试报告并分析结果 15 | 16 | #### 二、项目介绍 17 | 18 | ​ 课堂派是一款高效在线课堂管理平台 19 | 20 | **已知环境:** 21 | 22 | - 课堂派网址:https://www.ketangpai.com/ha 23 | 24 | - 加入考核班级邀请码:P69UVV 25 | 26 | **需要用自动化框架实现的功能**: 27 | 28 | ​ 3.1 课堂:加入班级、进入班级、 退课 29 | 30 | ​ 3.2 作业:上传作业、作业留言、查看作业提交状态 31 | 32 | ​ 3.3 私信:发送私信 33 | 34 | #### 三、设计测试用例 35 | 36 | ##### 1.登录 37 | 38 | | 登录功能测试步骤 | 39 | | ------------------------------------------------------------ | 40 | | **前置条件**:联网
1.打开浏览器,初始化
(执行一次) | 41 | | (刷新页面,可重复执行多次)
2.输入页面地址或刷新
3.定位用户名
4.输入用户名
5.定位密码
6.输入密码
7.定位登录按钮
8.点击提交
9.定位用户的账号信息,断言(8.定位错误信息,断言) | 42 | 43 | ##### 2.课堂 44 | 45 | | 2.1 加入班级 | 2.2 进入班级 | 2.3 退出班级 | 46 | | ------------------------------------------------------------ | ----------------------------------------- | ------------------------------------------------------------ | 47 | | **前置条件**:已登录 | **前置条件**:已登录+已加入班级 | **前置条件**:已登录+已加入班级
1.登录
2.执行加入班级操作
3.判断,已加入则取消,未加入则继续
| 48 | | 1.定位加入课程
2.点击
3.定位加课验证码输入框
4.输入加课码
5.定位加入按钮
6.点击提交
7.定位加入成功信息,断言(定位错误信息,断言) | 1.定位班级
2.点击跳转至class界面
| 1.定位更多,点击
2.定位退课,点击
3.定位登录密码输入框
4.输入密码
5.定位退课按钮
6.点击提交
7.定位退课成功信息,断言(定位错误信息,断言) | 49 | 50 | ##### 3.作业 51 | 52 | 分析:有两种情况: 53 | 54 | - 第一次提交 55 | - 更新提交 56 | 57 | | 3.1 上传作业 | 3.2 作业留言 | 3.3 查看作业提交状态 | 58 | | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | 59 | | **前置条件**:已登录+已加入班级+已进入作业页面
1.定位班级
2.点击跳转至class界面
3.定位作业,点击
4.定位作业标题
5.点击跳转至homework界面 | **前置条件**:已登录+已加入班级+已进入班级+已进入作业页面
1.定位班级
2.点击跳转至class界面
3.定位作业,点击
4.定位作业标题
5.点击跳转至homework界面 | **前置条件**:已登录+已加入班级+已进入作业页面
1.定位班级
2.点击跳转至class界面
3.定位作业,点击
4.定位作业标题
5.点击跳转至homework界面 | 60 | | 6.1定位添加作业文件按钮,点击
6.2定位更新提交按钮,点击
7.上传文件操作
8.定位提交按钮,点击提交
9.定位提交成功信息,断言(定位错误信息,断言) | 6.定位作业留言按钮,点击
7.定位留言输入框
8.清空输入框
9.输入留言
10.定位保存按钮,点击提交
11.定位作业留言按钮,获取留言信息,断言 | 6.定位作业留言按钮,点击
7.定位留言输入框
8.输入留言
9.定位保存按钮,点击提交
10.定位作业留言按钮,获取留言信息,断言 | 61 | 62 | ##### 4.私信 63 | 64 | | 私信功能测试步骤 | 65 | | ------------------------------------------------------------ | 66 | | **前置条件**:已登录+已加入班级+已进入班级+已进入students界面
1.定位班级
2.点击跳转至course界面
3.定位同学
4.点击跳转至student界面 | 67 | | 5.定位全部学生,点击
6.定位第一个学生,鼠标悬停
7.定位call图标,点击
8.定位会话输入框
9.输入消息
10.定位发送按钮
11.点击提交
12.定位发送的文本,断言 | 68 | 69 | #### 四、自动化测试环境 70 | 71 | python + selenium + pytest + chrom 72 | 73 | #### [Jenkins集成allure测试报告](https://www.cnblogs.com/linuxchao/p/linuxchao-jenkins-allure.html) --------------------------------------------------------------------------------