New file |
| | |
| | | from selenium.common import TimeoutException |
| | | from selenium.webdriver.support.wait import WebDriverWait |
| | | from selenium.webdriver.support import expected_conditions as EC |
| | | |
| | | class BasePage: |
| | | # 初始化方法 |
| | | def __init__(self, driver): |
| | | self.driver = driver |
| | | |
| | | # 元素定位 |
| | | def get_element(self, locator): |
| | | return self.driver.find_element(*locator) |
| | | |
| | | # 多个元素定位 |
| | | def get_elements(self, locator): |
| | | return self.driver.find_elements(*locator) |
| | | |
| | | # 多个元素定位 |
| | | def get_elements_wait(self, locator): |
| | | wait = WebDriverWait(self.driver, 10, 0.5) |
| | | wait.until(EC.presence_of_element_located(locator)) |
| | | return self.driver.find_elements(*locator) |
| | | |
| | | # 在指定元素中定位元素 |
| | | def get_element_in(self, element, locator): |
| | | return element.find_element(*locator) |
| | | |
| | | # 在指定元素中定位多个元素 |
| | | def get_elements_in(self, element, *locator): |
| | | return element.find_elements(*locator) |
| | | |
| | | # 元素定位 |
| | | def get_element_wait(self, locator): |
| | | wait = WebDriverWait(self.driver, 10, 0.5) |
| | | wait.until(EC.presence_of_element_located(locator)) |
| | | return self.driver.find_element(*locator) |
| | | |
| | | # 使用js语句点击 |
| | | def script_click(self, *locator): |
| | | item = self.get_element(*locator) |
| | | self.driver.execute_script("arguments[0].click();", item) |
| | | |
| | | def script_click_wait(self, *locator): |
| | | item = self.get_element_wait(*locator) |
| | | self.driver.execute_script("arguments[0].click();", item) |
| | | |
| | | # 点击 |
| | | def click(self, locator): |
| | | """ |
| | | 点击元素 |
| | | :param locator: 元素定位 |
| | | :return: |
| | | """ |
| | | self.get_element(locator).click() |
| | | |
| | | def click_wait(self, *locator): |
| | | self.get_element_wait(*locator).click() |
| | | |
| | | # 输入 |
| | | def send_text(self, text, locator): |
| | | """ |
| | | 输入内容 |
| | | :param text: 内容 |
| | | :param locator: 元素定位 |
| | | :return: |
| | | """ |
| | | self.get_element(locator).send_keys(text) |
| | | |
| | | def send_text_wait(self, text, *locator): |
| | | self.get_element_wait(*locator).send_keys(text) |
| | | |
| | | # JavaScript获取元素值 |
| | | def get_input_value_js(self, locator): |
| | | input_box = self.get_element(locator) |
| | | input_value = self.driver.execute_script("return arguments[0].value", input_box) |
| | | return input_value |
| | | |
| | | def get_input_value_js_wait(self, *locator): |
| | | input_box = self.get_element_wait(*locator) |
| | | input_value = self.driver.execute_script("return arguments[0].value", input_box) |
| | | return input_value |
| | | |
| | | # 清除 |
| | | def clear_text(self, *locator): |
| | | self.get_element(*locator).clear() |
| | | |
| | | def clear_text_wait(self, *locator): |
| | | self.get_element_wait(*locator).clear() |
| | | |
| | | # 表单切换 |
| | | def switch_iframe(self, locator): |
| | | self.driver.switch_to.frame(self.get_element(locator)) |
| | | |
| | | # 切换到上一层的iframe |
| | | def switch_parent_iframe(self): |
| | | self.driver.switch_to.parent_frame() |
| | | |
| | | def switch_iframe_wait(self, locator): |
| | | self.driver.switch_to.frame(self.get_element_wait(locator)) |
| | | |
| | | # 窗口切换 |
| | | def switch_window(self, n): |
| | | self.driver.switch_to.window(self.driver.window_handles[n]) |
| | | |
| | | # 检查元素是否可见可点击 |
| | | def check_clickable(self, *locator): |
| | | wait = WebDriverWait(self.driver, 10, 0.5) |
| | | try: |
| | | e = wait.until(EC.element_to_be_clickable(locator)) |
| | | if e is not None: |
| | | return True |
| | | except TimeoutException: |
| | | pass |
| | | return False |
| | | |
| | | # 等待元素出现 |
| | | def wait_appear(self, *locator): |
| | | wait = WebDriverWait(self.driver, 10, 0.5) |
| | | try: |
| | | e = wait.until(EC.presence_of_element_located(locator)) |
| | | if e is not None: |
| | | return True |
| | | except TimeoutException: |
| | | pass |
| | | return False |
| | | |
| | | # 滑动页面 |
| | | def scroll_by(self, num): |
| | | self.driver.execute_script("window.scrollBy(0, " + num + ");") |
| | | |
| | | # 滑动到底部 |
| | | def scroll_to_bottom(self): |
| | | self.driver.execute_script("window.scrollBy(0,document.body.scrollHeight);") |
| | | |
| | | # 滑动到顶部 |
| | | def scroll_to_top(self): |
| | | self.driver.execute_script("window.scrollBy(0,0);") |
| | | |
| | | # 截取当前窗口保存为图片 |
| | | def get_png(self): |
| | | """截取当前窗口保存为图片""" |
| | | return self.driver.get_screenshot_as_png() |
| | | |
| | | def open_new_table_to_url(self, url): |
| | | """ |
| | | 打开一个新的标签页,并跳转到指定的url |
| | | :return: |
| | | """ |
| | | # 打开新标签页 |
| | | self.driver.execute_script("window.open()") |
| | | # 切换到新的标签页 |
| | | self.switch_window(-1) |
| | | # 在新标签页中加载指定url |
| | | self.driver.get(url) |
New file |
| | |
| | | import random |
| | | import string |
| | | |
| | | |
| | | # 生成随机字符串 |
| | | def random_string(length): |
| | | letters = string.ascii_letters + string.digits |
| | | return ''.join(random.choice(letters) for _ in range(length)) |
| | | |
| | | |
| | | # 生成随机邮箱地址 |
| | | def random_email(domain): |
| | | username = random_string(8) # 生成8个字符的随机用户名 |
| | | email = f"{username}@{domain}" # 根据随机用户名和指定的域名生成邮箱地址 |
| | | return email |
New file |
| | |
| | | from selenium.webdriver.common.by import By |
| | | |
| | | |
| | | class AnswerElements: |
| | | # 题目选项 |
| | | options = (By.XPATH, "//span[@class='q-item-span-content']") |
| | | # 禁用的选项 |
| | | disabled = (By.XPATH, "//label[@aria-disabled='true']") |
| | | # 继续测试按钮 |
| | | continue_testing_btn = (By.XPATH, "//button/span[text()='继续测试']") |
| | | # 提交按钮 |
| | | submit_btn = (By.XPATH, "//button/span[contains(text(),'提交')]") |
| | | # 上传成功标题 |
| | | upload_success_title = (By.XPATH, "//main/h2[contains(text(), '数据已经成功地上传至服务器')]") |
| | | |
| | | # 加载框文字 |
| | | loading_text = (By.XPATH, "//div[@class='el-loading-spinner']/p") |
| | | |
New file |
| | |
| | | from selenium.webdriver.common.by import By |
| | | |
| | | |
| | | class HomeElements: |
| | | # 侧边栏菜单 |
| | | menu_ul = (By.XPATH, "//ul[@id='side-menu']") |
| | | |
| | | |
New file |
| | |
| | | from selenium.webdriver.common.by import By |
| | | |
| | | |
| | | class LoginElements: |
| | | # 登录用户名输入框 |
| | | username_input = (By.XPATH, "//form//input[@name='username']") |
| | | # 登录密码输入框 |
| | | password_input = (By.XPATH, "//form//input[@name='password']") |
| | | # 验证码输入框 |
| | | validate_code_input = (By.XPATH, "//form//input[@name='validateCode']") |
| | | # 登录按钮 |
| | | login_btn = (By.XPATH, "//form//button") |
| | | |
New file |
| | |
| | | from selenium.webdriver.common.by import By |
| | | |
| | | |
| | | class ShareAddElements: |
| | | # 姓名 |
| | | name = (By.XPATH, "//input[@name='memberName']") |
| | | # 邮箱 |
| | | email = (By.XPATH, "//textarea[@name='memberEmail']") |
| | | # 手机号码 |
| | | phone = (By.XPATH, "//textarea[@name='memberPhone']") |
| | | # 提交按钮 |
| | | submit_btn = (By.XPATH, "//button") |
| | | |
| | | # 测试链接 |
| | | test_url = (By.XPATH, "//a") |
| | | |
| | | # 基本信息-电子邮箱 |
| | | fill_email = (By.XPATH, "//form/div[2]//input") |
| | | # 基本信息-职位 |
| | | fill_position = (By.XPATH, "//form/div[3]//input") |
| | | # 基本信息-部门 |
| | | fill_dept = (By.XPATH, "//form/div[4]//input") |
New file |
| | |
| | | from selenium.webdriver.common.by import By |
| | | |
| | | |
| | | class TestPackageListElements: |
| | | # 测试包列表iframe |
| | | this_iframe = (By.XPATH, "//iframe[@src='/exam/test_package']") |
| | | # 添加测试包iframe |
| | | add_iframe = (By.XPATH, "//iframe[@src='/exam/test_package/add']") |
| | | # 产品包树iframe |
| | | prodTree_iframe = (By.XPATH, "//iframe[contains(@src,'/exam/product/getProdList')]") |
| | | # 分享iframe |
| | | share_iframe = (By.XPATH, "//iframe[contains(@src,'/exam/test_package/share')]") |
| | | |
| | | |
| | | # this-创建按钮 |
| | | create_btn = (By.XPATH, "//a[@onclick='$.operate.add()']") |
| | | # this-测试包列表测试包名称a标签 |
| | | table_packageName_a = (By.XPATH, "//table[@id='bootstrap-table']/tbody/tr/td[2]/a") |
| | | # this-列表tr |
| | | table_package_tr = (By.XPATH, "//table[@id='bootstrap-table']/tbody/tr") |
| | | # this-生成分享链接按钮 |
| | | share_1_btn = (By.XPATH, "//a[@onclick='share(1)']") |
| | | # this-删除按钮 |
| | | delete_btn = (By.XPATH, "//a[@onclick='$.operate.removeAll()']") |
| | | # this-删除确认按钮 |
| | | delete_confirm_btn = (By.XPATH, "//div/a[text()='确认']") |
| | | |
| | | # add-测试包名称 |
| | | add_testPackageName_input = (By.XPATH, "//input[@name='testName']") |
| | | # add-报告企业名称 |
| | | add_reportCompanyName_input = (By.XPATH, "//input[@name='reportCompanyName']") |
| | | # add-类型 |
| | | add_testPackageType_select = (By.XPATH, "//select[@name='testType']/../span") |
| | | # add-类型选项 |
| | | add_testPackageType_option = (By.XPATH, "//ul[contains(@id,'select2-testType')]/li") |
| | | # add-区域 |
| | | add_testPackageArea_select = (By.XPATH, "//select[@name='testArea']/../span") |
| | | # add-区域选项 |
| | | add_testPackageArea_option = (By.XPATH, "//ul[contains(@id,'select2-testArea')]/li") |
| | | # add-产品包树弹出按钮 |
| | | add_prodTree_btn = (By.XPATH, "//span[@onclick='selectProdTree()']") |
| | | # add-HR接收报告邮箱 |
| | | add_hrEmail_input = (By.XPATH, "//input[@name='testEmail']") |
| | | # add-有效期 |
| | | add_invalidTime = (By.XPATH, "//input[@name='invalidTime']") |
| | | # add-测试者邀请邮件内容模板 |
| | | add_templateLangType_select = (By.XPATH, "//select[@name='templateLangType']/../button") |
| | | # add-测试者邀请邮件内容模板选项 |
| | | add_templateLangType_option = (By.XPATH, "//select[@name='templateLangType']/../div/div/ul/li/a/span[2]") |
| | | # add-HR语言类型 |
| | | add_hrTemplateLangType_select = (By.XPATH, "//select[@name='hrTemplateLangType']/../button") |
| | | # add-HR语言类型选项 |
| | | add_hrTemplateLangType_option = (By.XPATH, "//select[@name='hrTemplateLangType']/../div/div/ul/li/a/span[2]") |
| | | # add-报告模板 |
| | | add_reportTemplateId_select = (By.XPATH, "//select[@name='reportTemplateId']/../button") |
| | | # add-报告模板选项 |
| | | add_reportTemplateId_option = (By.XPATH, "//select[@name='reportTemplateId']/../div/div/ul/li/a/span[2]") |
| | | # add-测试者接收报告 |
| | | add_autoSendReport_checkbox = (By.XPATH, "//input[@name='autoSendReport']") |
| | | # add-测试者报告语言类型 |
| | | add_memberTemplateLangType_select = (By.XPATH, "//select[@name='memberTemplateLangType']/../button") |
| | | # add-测试者报告语言类型选项 |
| | | add_memberTemplateLangType_option = (By.XPATH, "//select[@name='memberTemplateLangType']/../div/div/ul/li/a/span[2]") |
| | | # add-确认按钮 |
| | | add_confirm_btn = (By.XPATH, "//iframe[@src='/exam/test_package/add']/../../div[3]/a[1]") |
| | | |
| | | # prodTree-产品包选项 |
| | | prodTree_option = (By.XPATH, "//div[@id='tree']/li/a/span[2]") |
| | | # proTree-确认按钮 |
| | | prodTree_confirm_btn = (By.XPATH, "//iframe[contains(@src,'/exam/product/getProdList')]/../../div[3]/a[1]") |
| | | |
| | | # share-url |
| | | share_url_input = (By.XPATH, "//input[@id='shareUrl']") |
| | | # share-关闭按钮 |
| | | share_cancel_btn = (By.XPATH, "//iframe[contains(@src,'/exam/test_package/share')]/../../div[3]/a[2]") |
New file |
| | |
| | | import pytest |
| | | import pytest_html |
| | | from testcase import test_smoking |
| | | |
| | | |
| | | def run_testcases(): |
| | | pytest.main(['-vs', '--html=report/report.html', 'testcase/test_smoking.py']) |
| | | |
| | | |
| | | if __name__ == '__main__': |
| | | run_testcases() |
New file |
| | |
| | | import random |
| | | |
| | | from base.base_page import BasePage |
| | | from elements.answer_elements import AnswerElements as Answer |
| | | import time |
| | | |
| | | |
| | | class AnswerPage(BasePage): |
| | | """ |
| | | 答题页面 |
| | | """ |
| | | loading_count = 0 |
| | | |
| | | def answer_MAQ(self): |
| | | # 获取到所有选项 |
| | | time.sleep(3) |
| | | |
| | | while True: |
| | | |
| | | # 判断是否一直存在加载框 |
| | | if self.loadin_text(): |
| | | return |
| | | |
| | | try: |
| | | # 点击继续测试按钮 |
| | | self.click(Answer.continue_testing_btn) |
| | | except: |
| | | pass |
| | | |
| | | try: |
| | | options = self.get_elements(Answer.options) |
| | | if len(options) < 6: |
| | | continue |
| | | number = random.randint(0, 5) |
| | | options[number].click() |
| | | except: |
| | | pass |
| | | |
| | | try: |
| | | # 点击提交按钮 |
| | | self.click(Answer.submit_btn) |
| | | except: |
| | | pass |
| | | |
| | | try: |
| | | # 数据上传完成 |
| | | self.get_element(Answer.upload_success_title) |
| | | return |
| | | except: |
| | | pass |
| | | |
| | | def loadin_text(self): |
| | | """ |
| | | 判断加载框加载,如果加载超过10秒直接退出当前测试 |
| | | :return: |
| | | """ |
| | | i = 0 |
| | | while i < 10: |
| | | try: |
| | | self.get_element(Answer.loading_text) |
| | | i += 1 |
| | | time.sleep(1) |
| | | except: |
| | | return False |
| | | else: |
| | | return True |
New file |
| | |
| | | from base.base_page import BasePage |
| | | from selenium.webdriver.common.by import By |
| | | import time |
| | | |
| | | |
| | | class HomePage(BasePage): |
| | | """ |
| | | 主页面侧边栏菜单与tab栏操作页面 |
| | | """ |
| | | |
| | | def menu_select(self, menu_text, is_first=True): |
| | | """ |
| | | 选择菜单 |
| | | :param menu_text: 菜单选项内容,使用 / 分隔上下级菜单 |
| | | :param is_first: 是否为一级菜单,默认为True |
| | | :return: |
| | | """ |
| | | # 判断menu_text是否包含/ |
| | | if "/" in menu_text: |
| | | # 包含 / 获取到第一个/前的菜单选项 |
| | | # 获取/第一次出现的位置 |
| | | index = menu_text.find("/") |
| | | # 截取要点击的菜单选项 |
| | | menu = menu_text[0:index] |
| | | else: |
| | | menu = menu_text |
| | | |
| | | # 判断是否一级菜单 |
| | | if is_first: |
| | | # 菜单元素定位 |
| | | menu_loc = (By.XPATH, "//ul[@id='side-menu']//span[text()='" + menu + "']") |
| | | # 获取菜单元素 |
| | | menu_element = self.get_element(menu_loc) |
| | | # 点击菜单 |
| | | menu_element.click() |
| | | time.sleep(1) |
| | | else: |
| | | # 菜单元素定位 |
| | | menu_loc = (By.XPATH, "//ul[@id='side-menu']//a[text()='" + menu + "']") |
| | | # 获取菜单元素 |
| | | menu_element = self.get_element(menu_loc) |
| | | # 点击菜单 |
| | | menu_element.click() |
| | | time.sleep(1) |
| | | |
| | | if "/" in menu_text: |
| | | # 获取/第一次出现的位置 |
| | | index = menu_text.find("/") |
| | | # 截取剩余的菜单内容 |
| | | menu_text = menu_text[index + 1: len(menu_text)] |
| | | # 递归调用 |
| | | self.menu_select(menu_text, False) |
New file |
| | |
| | | from base.base_page import BasePage |
| | | from elements.login_elements import LoginElements as Login |
| | | |
| | | |
| | | class LoginPage(BasePage): |
| | | """ |
| | | 登录页面 |
| | | """ |
| | | |
| | | def username_input(self, username): |
| | | """ |
| | | 填写用户名 |
| | | :param username: 用户名 |
| | | :return: |
| | | """ |
| | | self.send_text(username, Login.username_input) |
| | | |
| | | def password_input(self, password): |
| | | """ |
| | | 填写密码 |
| | | :param password: 密码 |
| | | :return: |
| | | """ |
| | | self.send_text(password, Login.password_input) |
| | | |
| | | def validate_code_input(self, validate_code): |
| | | """ |
| | | 填写验证码 |
| | | :param validate_code: 验证码 |
| | | :return: |
| | | """ |
| | | self.send_text(validate_code, Login.validate_code_input) |
| | | |
| | | def login_btn(self): |
| | | """ |
| | | 点击登录按钮 |
| | | :return: |
| | | """ |
| | | self.click(Login.login_btn) |
| | | |
| | | def login(self, username, password, validate_code): |
| | | """ |
| | | 登录 |
| | | :param username: 用户名 |
| | | :param password: 密码 |
| | | :param validate_code: 验证码 |
| | | :return: |
| | | """ |
| | | self.username_input(username) |
| | | self.password_input(password) |
| | | self.validate_code_input(validate_code) |
| | | self.login_btn() |
| | | |
| | | def is_login_success(self): |
| | | """ |
| | | 判断是否登录成功 |
| | | :return: bool |
| | | """ |
| | | current_url = self.driver.current_url |
| | | if "index" in self.driver.current_url: |
| | | return True |
| | | else: |
| | | return False |
| | | |
| | | |
New file |
| | |
| | | from base.base_page import BasePage |
| | | from elements.share_add_elements import ShareAddElements as Share |
| | | import time |
| | | |
| | | |
| | | class ShareAddPage(BasePage): |
| | | """ |
| | | 分享链接打开的页面 |
| | | """ |
| | | def name_input(self, name): |
| | | """ |
| | | 输入姓名 |
| | | :param name: |
| | | :return: |
| | | """ |
| | | self.send_text(name, Share.name) |
| | | |
| | | def email_input(self, email): |
| | | """ |
| | | 输入邮箱 |
| | | :param email: |
| | | :return: |
| | | """ |
| | | self.send_text(email, Share.email) |
| | | |
| | | def submit_btn(self): |
| | | """ |
| | | 点击提交 |
| | | :return: |
| | | """ |
| | | self.click_wait(Share.submit_btn) |
| | | |
| | | def page_default_operation(self, name, email): |
| | | """ |
| | | 页面默认操作 |
| | | :param name: |
| | | :param email: |
| | | :return: |
| | | """ |
| | | # 输入姓名 |
| | | self.name_input(name) |
| | | # 输入邮箱 |
| | | self.email_input(email) |
| | | # 点击提交 |
| | | self.submit_btn() |
| | | # 获取测试链接并返回 |
| | | return self.get_element_wait(Share.test_url).text |
| | | |
| | | def fill_info(self, email, position, dept): |
| | | """ |
| | | 填写基本信息 |
| | | :param email: 邮箱 |
| | | :param position: 职位 |
| | | :param dept: 部门 |
| | | :return: |
| | | """ |
| | | self.send_text_wait(email, Share.fill_email) |
| | | self.send_text_wait(position, Share.fill_position) |
| | | self.send_text_wait(dept, Share.fill_dept) |
| | | self.click(Share.submit_btn) |
| | | time.sleep(2) |
| | | |
New file |
| | |
| | | from base.base_page import BasePage |
| | | from selenium.webdriver.common.by import By |
| | | from elements.test_package_list_elements import TestPackageListElements as PackageList |
| | | import time |
| | | |
| | | |
| | | class TestPackageListPage(BasePage): |
| | | """ |
| | | 测试包列表页面 |
| | | """ |
| | | |
| | | def __init__(self, driver): |
| | | """初始化时将iframe切换到当前页面""" |
| | | super().__init__(driver) |
| | | try: |
| | | self.driver.switch_to.default_content() |
| | | self.switch_iframe(PackageList.this_iframe) |
| | | except: |
| | | pass |
| | | |
| | | def create_btn(self): |
| | | """ |
| | | 点击创建按钮 |
| | | :return: |
| | | """ |
| | | self.click(PackageList.create_btn) |
| | | # 切换到add窗口的iframe |
| | | self.switch_iframe(PackageList.add_iframe) |
| | | |
| | | def delete_package(self): |
| | | """ |
| | | 删除测试包 |
| | | :return: |
| | | """ |
| | | # 点击删除按钮 |
| | | self.click(PackageList.delete_btn) |
| | | # 点击确认按钮 |
| | | self.click_wait(PackageList.delete_confirm_btn) |
| | | |
| | | def testPackageName_input(self, testPackageName): |
| | | """ |
| | | 输入测试包名称 |
| | | :param testPackageName: 测试包名称 |
| | | :return: |
| | | """ |
| | | self.send_text(testPackageName, PackageList.add_testPackageName_input) |
| | | |
| | | def reportCompanyName_input(self, reportCompanyName): |
| | | """ |
| | | 输入报告企业名称 |
| | | :param reportCompanyName: 报告企业名称 |
| | | :return: |
| | | """ |
| | | self.send_text(reportCompanyName, PackageList.add_reportCompanyName_input) |
| | | |
| | | def testPackageType_select(self, testPackageType): |
| | | """ |
| | | 选择测试包类型 |
| | | :param testPackageType: |
| | | :return: |
| | | """ |
| | | # 点击下拉框 |
| | | self.click(PackageList.add_testPackageType_select) |
| | | # 获取所有选项 |
| | | options = self.get_elements(PackageList.add_testPackageType_option) |
| | | # 判断选项是否与传入的选项相等 |
| | | for opt in options: |
| | | if opt.text == testPackageType: |
| | | # 相等则点击该选项 |
| | | opt.click() |
| | | break |
| | | |
| | | def prodTree_select(self, prodName): |
| | | """ |
| | | 选择产品包 |
| | | :param prodName: |
| | | :return: |
| | | """ |
| | | # 点击查询按钮 |
| | | self.click(PackageList.add_prodTree_btn) |
| | | # 切换到prodTree的iframe |
| | | self.switch_iframe_wait(PackageList.prodTree_iframe) |
| | | time.sleep(2) |
| | | # 获取所有选项 |
| | | options = self.get_elements(PackageList.prodTree_option) |
| | | # 判断选项是否与传入选项相等 |
| | | for opt in options: |
| | | if opt.text == prodName: |
| | | opt.click() |
| | | break |
| | | # 切换到上一层的iframe |
| | | self.switch_parent_iframe() |
| | | # 点击确认按钮 |
| | | self.click(PackageList.prodTree_confirm_btn) |
| | | |
| | | def hrReportEmail_input(self, hr_email): |
| | | """ |
| | | 输入HR接收报告邮箱 |
| | | :param hr_email: |
| | | :return: |
| | | """ |
| | | self.send_text(hr_email, PackageList.add_hrEmail_input) |
| | | |
| | | def invalidTime_input(self, invalid_time): |
| | | """ |
| | | 输入有效期 |
| | | :param invalid_time: |
| | | :return: |
| | | """ |
| | | self.send_text(invalid_time, PackageList.add_invalidTime) |
| | | self.click(PackageList.add_invalidTime) |
| | | |
| | | def testTemplateLangType_select(self, text): |
| | | """ |
| | | 选择测试者邀请邮件内容模板 |
| | | :param text: 语言类型,可以选择多个,使用 , 分隔 |
| | | :return: |
| | | """ |
| | | # 分割text |
| | | lang_types = text.split(",") |
| | | # 点击下拉框 |
| | | self.click(PackageList.add_templateLangType_select) |
| | | # 获取所有选项 |
| | | options = self.get_elements(PackageList.add_templateLangType_option) |
| | | # 判断选项是否与传入的选项相等 |
| | | for opt in options: |
| | | for lang_type in lang_types: |
| | | if opt.text == lang_type: |
| | | # 相等则点击该选项 |
| | | opt.click() |
| | | break |
| | | |
| | | def hrTemplateLangType_select(self, text): |
| | | """ |
| | | 选择HR邮件内容模板 |
| | | :param text: 语言类型,可以选择多个,使用 , 分隔 |
| | | :return: |
| | | """ |
| | | # 分割text |
| | | lang_types = text.split(",") |
| | | # 点击下拉框 |
| | | self.click(PackageList.add_hrTemplateLangType_select) |
| | | # 获取所有选项 |
| | | options = self.get_elements(PackageList.add_hrTemplateLangType_option) |
| | | # 判断选项是否与传入的选项相等 |
| | | for opt in options: |
| | | for lang_type in lang_types: |
| | | if opt.text == lang_type: |
| | | # 相等则点击该选项 |
| | | opt.click() |
| | | break |
| | | |
| | | def reportTemplate_select(self, text): |
| | | """ |
| | | 报告模板选择 |
| | | :param text: 模板,可以选择多个,使用 , 分隔 |
| | | :return: |
| | | """ |
| | | # 分割text |
| | | templates = text.split(",") |
| | | # 点击下拉框 |
| | | self.click(PackageList.add_reportTemplateId_select) |
| | | # 获取所有选项 |
| | | options = self.get_elements(PackageList.add_reportTemplateId_option) |
| | | # 判断选项是否与传入的选项相等 |
| | | for opt in options: |
| | | for template in templates: |
| | | if opt.text == template: |
| | | # 相等则点击该选项 |
| | | opt.click() |
| | | break |
| | | # 再次点击下拉框 |
| | | self.click(PackageList.add_reportTemplateId_select) |
| | | |
| | | def autoSendReport_checkbox(self): |
| | | """ |
| | | 点击测试者接收报告 |
| | | :return: |
| | | """ |
| | | self.click(PackageList.add_autoSendReport_checkbox) |
| | | |
| | | def memberReportLangType_select(self, text): |
| | | """ |
| | | 测试者报告邮件语言类型 |
| | | :param text: 语言类型,可以选择多个,使用 , 分隔 |
| | | :return: |
| | | """ |
| | | # 分割text |
| | | lang_types = text.split(",") |
| | | # 点击下拉框 |
| | | self.click(PackageList.add_memberTemplateLangType_select) |
| | | # 获取所有选项 |
| | | options = self.get_elements(PackageList.add_memberTemplateLangType_option) |
| | | # 判断选项是否与传入的选项相等 |
| | | for opt in options: |
| | | for lang_type in lang_types: |
| | | if opt.text == lang_type: |
| | | # 相等则点击该选项 |
| | | opt.click() |
| | | break |
| | | |
| | | def add_confirm(self): |
| | | """ |
| | | 点击确认按钮 |
| | | :return: |
| | | """ |
| | | # 回到上一层iframe |
| | | self.switch_parent_iframe() |
| | | self.click(PackageList.add_confirm_btn) |
| | | |
| | | def is_create_success(self, packageName): |
| | | """ |
| | | 判断这个测试包是否创建成功 |
| | | :param packageName: 测试包名称 |
| | | :return: bool |
| | | """ |
| | | names = self.get_elements(PackageList.table_packageName_a) |
| | | for name in names: |
| | | if name.text == packageName: |
| | | return True |
| | | return False |
| | | |
| | | def click_package_checkbox(self, packageName): |
| | | """ |
| | | 选中测试包,勾选对应测试包列表的复选框 |
| | | :param packageName: 测试包名称 |
| | | :return: |
| | | """ |
| | | # 获取到table的所有tr |
| | | table_trs = self.get_elements(PackageList.table_package_tr) |
| | | for tr in table_trs: |
| | | # 测试包名称在tr中的定位 |
| | | package_name_loc = (By.XPATH, "td[2]/a") |
| | | # 获取tr中的测试包名称 |
| | | tr_package_name = self.get_element_in(tr, package_name_loc).text |
| | | if tr_package_name == packageName: |
| | | # 复选框在tr中的定位 |
| | | package_checkbox_loc = (By.XPATH, "td[1]/input") |
| | | # 获取复选框元素 |
| | | tr_checkbox = self.get_element_in(tr, package_checkbox_loc) |
| | | # 点击复选框 |
| | | tr_checkbox.click() |
| | | break |
| | | |
| | | def click_share_1_btn(self): |
| | | """ |
| | | 点击生成分享链接按钮 |
| | | :return: |
| | | """ |
| | | self.click(PackageList.share_1_btn) |
| | | |
| | | def get_share_url(self): |
| | | """ |
| | | 获取分享链接 |
| | | :return: url |
| | | """ |
| | | # 切换到share的iframe中 |
| | | self.switch_iframe(PackageList.share_iframe) |
| | | # 获取url |
| | | url = self.get_input_value_js(PackageList.share_url_input) |
| | | # 退回上一层iframe |
| | | self.switch_parent_iframe() |
| | | # 点击关闭按钮 |
| | | self.click(PackageList.share_cancel_btn) |
| | | return url |
| | | |
| | | |
| | | def selector(self, click_loc, options_loc, text): |
| | | """ |
| | | 通用选择器,直接调用选择下拉框选项 |
| | | :param click_loc: 点击后出现下拉选项的元素定位 |
| | | :param options_loc: 选项的元素定位 |
| | | :param text: 判断点击的文本 |
| | | :return: |
| | | """ |
| | | # 点击下拉框 |
| | | self.click(click_loc) |
| | | # 获取所有选项 |
| | | options = self.get_elements(options_loc) |
| | | # 判断选项是否与传入的选项相等 |
| | | for opt in options: |
| | | if opt.text == text: |
| | | # 相等则点击该选项 |
| | | opt.click() |
| | | break |
New file |
| | |
| | | body { |
| | | font-family: Helvetica, Arial, sans-serif; |
| | | font-size: 12px; |
| | | /* do not increase min-width as some may use split screens */ |
| | | min-width: 800px; |
| | | color: #999; |
| | | } |
| | | |
| | | h1 { |
| | | font-size: 24px; |
| | | color: black; |
| | | } |
| | | |
| | | h2 { |
| | | font-size: 16px; |
| | | color: black; |
| | | } |
| | | |
| | | p { |
| | | color: black; |
| | | } |
| | | |
| | | a { |
| | | color: #999; |
| | | } |
| | | |
| | | table { |
| | | border-collapse: collapse; |
| | | } |
| | | |
| | | /****************************** |
| | | * SUMMARY INFORMATION |
| | | ******************************/ |
| | | #environment td { |
| | | padding: 5px; |
| | | border: 1px solid #E6E6E6; |
| | | } |
| | | #environment tr:nth-child(odd) { |
| | | background-color: #f6f6f6; |
| | | } |
| | | |
| | | /****************************** |
| | | * TEST RESULT COLORS |
| | | ******************************/ |
| | | span.passed, |
| | | .passed .col-result { |
| | | color: green; |
| | | } |
| | | |
| | | span.skipped, |
| | | span.xfailed, |
| | | span.rerun, |
| | | .skipped .col-result, |
| | | .xfailed .col-result, |
| | | .rerun .col-result { |
| | | color: orange; |
| | | } |
| | | |
| | | span.error, |
| | | span.failed, |
| | | span.xpassed, |
| | | .error .col-result, |
| | | .failed .col-result, |
| | | .xpassed .col-result { |
| | | color: red; |
| | | } |
| | | |
| | | /****************************** |
| | | * RESULTS TABLE |
| | | * |
| | | * 1. Table Layout |
| | | * 2. Extra |
| | | * 3. Sorting items |
| | | * |
| | | ******************************/ |
| | | /*------------------ |
| | | * 1. Table Layout |
| | | *------------------*/ |
| | | #results-table { |
| | | border: 1px solid #e6e6e6; |
| | | color: #999; |
| | | font-size: 12px; |
| | | width: 100%; |
| | | } |
| | | #results-table th, |
| | | #results-table td { |
| | | padding: 5px; |
| | | border: 1px solid #E6E6E6; |
| | | text-align: left; |
| | | } |
| | | #results-table th { |
| | | font-weight: bold; |
| | | } |
| | | |
| | | /*------------------ |
| | | * 2. Extra |
| | | *------------------*/ |
| | | .log { |
| | | background-color: #e6e6e6; |
| | | border: 1px solid #e6e6e6; |
| | | color: black; |
| | | display: block; |
| | | font-family: "Courier New", Courier, monospace; |
| | | height: 230px; |
| | | overflow-y: scroll; |
| | | padding: 5px; |
| | | white-space: pre-wrap; |
| | | } |
| | | .log:only-child { |
| | | height: inherit; |
| | | } |
| | | |
| | | div.image { |
| | | border: 1px solid #e6e6e6; |
| | | float: right; |
| | | height: 240px; |
| | | margin-left: 5px; |
| | | overflow: hidden; |
| | | width: 320px; |
| | | } |
| | | div.image img { |
| | | width: 320px; |
| | | } |
| | | |
| | | div.video { |
| | | border: 1px solid #e6e6e6; |
| | | float: right; |
| | | height: 240px; |
| | | margin-left: 5px; |
| | | overflow: hidden; |
| | | width: 320px; |
| | | } |
| | | div.video video { |
| | | overflow: hidden; |
| | | width: 320px; |
| | | height: 240px; |
| | | } |
| | | |
| | | .collapsed { |
| | | display: none; |
| | | } |
| | | |
| | | .expander::after { |
| | | content: " (show details)"; |
| | | color: #BBB; |
| | | font-style: italic; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .collapser::after { |
| | | content: " (hide details)"; |
| | | color: #BBB; |
| | | font-style: italic; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | /*------------------ |
| | | * 3. Sorting items |
| | | *------------------*/ |
| | | .sortable { |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .sort-icon { |
| | | font-size: 0px; |
| | | float: left; |
| | | margin-right: 5px; |
| | | margin-top: 5px; |
| | | /*triangle*/ |
| | | width: 0; |
| | | height: 0; |
| | | border-left: 8px solid transparent; |
| | | border-right: 8px solid transparent; |
| | | } |
| | | .inactive .sort-icon { |
| | | /*finish triangle*/ |
| | | border-top: 8px solid #E6E6E6; |
| | | } |
| | | .asc.active .sort-icon { |
| | | /*finish triangle*/ |
| | | border-bottom: 8px solid #999; |
| | | } |
| | | .desc.active .sort-icon { |
| | | /*finish triangle*/ |
| | | border-top: 8px solid #999; |
| | | } |
New file |
| | |
| | | <!DOCTYPE html> |
| | | <html> |
| | | <head> |
| | | <meta charset="utf-8"/> |
| | | <title>report.html</title> |
| | | <link href="assets/style.css" rel="stylesheet" type="text/css"/></head> |
| | | <body onLoad="init()"> |
| | | <script>/* This Source Code Form is subject to the terms of the Mozilla Public |
| | | * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
| | | * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| | | |
| | | |
| | | function toArray(iter) { |
| | | if (iter === null) { |
| | | return null; |
| | | } |
| | | return Array.prototype.slice.call(iter); |
| | | } |
| | | |
| | | function find(selector, elem) { // eslint-disable-line no-redeclare |
| | | if (!elem) { |
| | | elem = document; |
| | | } |
| | | return elem.querySelector(selector); |
| | | } |
| | | |
| | | function findAll(selector, elem) { |
| | | if (!elem) { |
| | | elem = document; |
| | | } |
| | | return toArray(elem.querySelectorAll(selector)); |
| | | } |
| | | |
| | | function sortColumn(elem) { |
| | | toggleSortStates(elem); |
| | | const colIndex = toArray(elem.parentNode.childNodes).indexOf(elem); |
| | | let key; |
| | | if (elem.classList.contains('result')) { |
| | | key = keyResult; |
| | | } else if (elem.classList.contains('links')) { |
| | | key = keyLink; |
| | | } else { |
| | | key = keyAlpha; |
| | | } |
| | | sortTable(elem, key(colIndex)); |
| | | } |
| | | |
| | | function showAllExtras() { // eslint-disable-line no-unused-vars |
| | | findAll('.col-result').forEach(showExtras); |
| | | } |
| | | |
| | | function hideAllExtras() { // eslint-disable-line no-unused-vars |
| | | findAll('.col-result').forEach(hideExtras); |
| | | } |
| | | |
| | | function showExtras(colresultElem) { |
| | | const extras = colresultElem.parentNode.nextElementSibling; |
| | | const expandcollapse = colresultElem.firstElementChild; |
| | | extras.classList.remove('collapsed'); |
| | | expandcollapse.classList.remove('expander'); |
| | | expandcollapse.classList.add('collapser'); |
| | | } |
| | | |
| | | function hideExtras(colresultElem) { |
| | | const extras = colresultElem.parentNode.nextElementSibling; |
| | | const expandcollapse = colresultElem.firstElementChild; |
| | | extras.classList.add('collapsed'); |
| | | expandcollapse.classList.remove('collapser'); |
| | | expandcollapse.classList.add('expander'); |
| | | } |
| | | |
| | | function showFilters() { |
| | | let visibleString = getQueryParameter('visible') || 'all'; |
| | | visibleString = visibleString.toLowerCase(); |
| | | const checkedItems = visibleString.split(','); |
| | | |
| | | const filterItems = document.getElementsByClassName('filter'); |
| | | for (let i = 0; i < filterItems.length; i++) { |
| | | filterItems[i].hidden = false; |
| | | |
| | | if (visibleString != 'all') { |
| | | filterItems[i].checked = checkedItems.includes(filterItems[i].getAttribute('data-test-result')); |
| | | filterTable(filterItems[i]); |
| | | } |
| | | } |
| | | } |
| | | |
| | | function addCollapse() { |
| | | // Add links for show/hide all |
| | | const resulttable = find('table#results-table'); |
| | | const showhideall = document.createElement('p'); |
| | | showhideall.innerHTML = '<a href="javascript:showAllExtras()">Show all details</a> / ' + |
| | | '<a href="javascript:hideAllExtras()">Hide all details</a>'; |
| | | resulttable.parentElement.insertBefore(showhideall, resulttable); |
| | | |
| | | // Add show/hide link to each result |
| | | findAll('.col-result').forEach(function(elem) { |
| | | const collapsed = getQueryParameter('collapsed') || 'Passed'; |
| | | const extras = elem.parentNode.nextElementSibling; |
| | | const expandcollapse = document.createElement('span'); |
| | | if (extras.classList.contains('collapsed')) { |
| | | expandcollapse.classList.add('expander'); |
| | | } else if (collapsed.includes(elem.innerHTML)) { |
| | | extras.classList.add('collapsed'); |
| | | expandcollapse.classList.add('expander'); |
| | | } else { |
| | | expandcollapse.classList.add('collapser'); |
| | | } |
| | | elem.appendChild(expandcollapse); |
| | | |
| | | elem.addEventListener('click', function(event) { |
| | | if (event.currentTarget.parentNode.nextElementSibling.classList.contains('collapsed')) { |
| | | showExtras(event.currentTarget); |
| | | } else { |
| | | hideExtras(event.currentTarget); |
| | | } |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | function getQueryParameter(name) { |
| | | const match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search); |
| | | return match && decodeURIComponent(match[1].replace(/\+/g, ' ')); |
| | | } |
| | | |
| | | function init () { // eslint-disable-line no-unused-vars |
| | | resetSortHeaders(); |
| | | |
| | | addCollapse(); |
| | | |
| | | showFilters(); |
| | | |
| | | sortColumn(find('.initial-sort')); |
| | | |
| | | findAll('.sortable').forEach(function(elem) { |
| | | elem.addEventListener('click', |
| | | function() { |
| | | sortColumn(elem); |
| | | }, false); |
| | | }); |
| | | } |
| | | |
| | | function sortTable(clicked, keyFunc) { |
| | | const rows = findAll('.results-table-row'); |
| | | const reversed = !clicked.classList.contains('asc'); |
| | | const sortedRows = sort(rows, keyFunc, reversed); |
| | | /* Whole table is removed here because browsers acts much slower |
| | | * when appending existing elements. |
| | | */ |
| | | const thead = document.getElementById('results-table-head'); |
| | | document.getElementById('results-table').remove(); |
| | | const parent = document.createElement('table'); |
| | | parent.id = 'results-table'; |
| | | parent.appendChild(thead); |
| | | sortedRows.forEach(function(elem) { |
| | | parent.appendChild(elem); |
| | | }); |
| | | document.getElementsByTagName('BODY')[0].appendChild(parent); |
| | | } |
| | | |
| | | function sort(items, keyFunc, reversed) { |
| | | const sortArray = items.map(function(item, i) { |
| | | return [keyFunc(item), i]; |
| | | }); |
| | | |
| | | sortArray.sort(function(a, b) { |
| | | const keyA = a[0]; |
| | | const keyB = b[0]; |
| | | |
| | | if (keyA == keyB) return 0; |
| | | |
| | | if (reversed) { |
| | | return keyA < keyB ? 1 : -1; |
| | | } else { |
| | | return keyA > keyB ? 1 : -1; |
| | | } |
| | | }); |
| | | |
| | | return sortArray.map(function(item) { |
| | | const index = item[1]; |
| | | return items[index]; |
| | | }); |
| | | } |
| | | |
| | | function keyAlpha(colIndex) { |
| | | return function(elem) { |
| | | return elem.childNodes[1].childNodes[colIndex].firstChild.data.toLowerCase(); |
| | | }; |
| | | } |
| | | |
| | | function keyLink(colIndex) { |
| | | return function(elem) { |
| | | const dataCell = elem.childNodes[1].childNodes[colIndex].firstChild; |
| | | return dataCell == null ? '' : dataCell.innerText.toLowerCase(); |
| | | }; |
| | | } |
| | | |
| | | function keyResult(colIndex) { |
| | | return function(elem) { |
| | | const strings = ['Error', 'Failed', 'Rerun', 'XFailed', 'XPassed', |
| | | 'Skipped', 'Passed']; |
| | | return strings.indexOf(elem.childNodes[1].childNodes[colIndex].firstChild.data); |
| | | }; |
| | | } |
| | | |
| | | function resetSortHeaders() { |
| | | findAll('.sort-icon').forEach(function(elem) { |
| | | elem.parentNode.removeChild(elem); |
| | | }); |
| | | findAll('.sortable').forEach(function(elem) { |
| | | const icon = document.createElement('div'); |
| | | icon.className = 'sort-icon'; |
| | | icon.textContent = 'vvv'; |
| | | elem.insertBefore(icon, elem.firstChild); |
| | | elem.classList.remove('desc', 'active'); |
| | | elem.classList.add('asc', 'inactive'); |
| | | }); |
| | | } |
| | | |
| | | function toggleSortStates(elem) { |
| | | //if active, toggle between asc and desc |
| | | if (elem.classList.contains('active')) { |
| | | elem.classList.toggle('asc'); |
| | | elem.classList.toggle('desc'); |
| | | } |
| | | |
| | | //if inactive, reset all other functions and add ascending active |
| | | if (elem.classList.contains('inactive')) { |
| | | resetSortHeaders(); |
| | | elem.classList.remove('inactive'); |
| | | elem.classList.add('active'); |
| | | } |
| | | } |
| | | |
| | | function isAllRowsHidden(value) { |
| | | return value.hidden == false; |
| | | } |
| | | |
| | | function filterTable(elem) { // eslint-disable-line no-unused-vars |
| | | const outcomeAtt = 'data-test-result'; |
| | | const outcome = elem.getAttribute(outcomeAtt); |
| | | const classOutcome = outcome + ' results-table-row'; |
| | | const outcomeRows = document.getElementsByClassName(classOutcome); |
| | | |
| | | for(let i = 0; i < outcomeRows.length; i++){ |
| | | outcomeRows[i].hidden = !elem.checked; |
| | | } |
| | | |
| | | const rows = findAll('.results-table-row').filter(isAllRowsHidden); |
| | | const allRowsHidden = rows.length == 0 ? true : false; |
| | | const notFoundMessage = document.getElementById('not-found-message'); |
| | | notFoundMessage.hidden = !allRowsHidden; |
| | | } |
| | | </script> |
| | | <h1>report.html</h1> |
| | | <p>Report generated on 12-Jul-2023 at 16:29:07 by <a href="https://pypi.python.org/pypi/pytest-html">pytest-html</a> v3.2.0</p> |
| | | <h2>Summary</h2> |
| | | <p>4 tests ran in 65.45 seconds. </p> |
| | | <p class="filter" hidden="true">(Un)check the boxes to filter the results.</p><input checked="true" class="filter" data-test-result="passed" hidden="true" name="filter_checkbox" onChange="filterTable(this)" type="checkbox"/><span class="passed">4 passed</span>, <input checked="true" class="filter" data-test-result="skipped" disabled="true" hidden="true" name="filter_checkbox" onChange="filterTable(this)" type="checkbox"/><span class="skipped">0 skipped</span>, <input checked="true" class="filter" data-test-result="failed" disabled="true" hidden="true" name="filter_checkbox" onChange="filterTable(this)" type="checkbox"/><span class="failed">0 failed</span>, <input checked="true" class="filter" data-test-result="error" disabled="true" hidden="true" name="filter_checkbox" onChange="filterTable(this)" type="checkbox"/><span class="error">0 errors</span>, <input checked="true" class="filter" data-test-result="xfailed" disabled="true" hidden="true" name="filter_checkbox" onChange="filterTable(this)" type="checkbox"/><span class="xfailed">0 expected failures</span>, <input checked="true" class="filter" data-test-result="xpassed" disabled="true" hidden="true" name="filter_checkbox" onChange="filterTable(this)" type="checkbox"/><span class="xpassed">0 unexpected passes</span> |
| | | <h2>Results</h2> |
| | | <table id="results-table"> |
| | | <thead id="results-table-head"> |
| | | <tr> |
| | | <th class="sortable result initial-sort" col="result">Result</th> |
| | | <th class="sortable" col="name">Test</th> |
| | | <th class="sortable" col="duration">Duration</th> |
| | | <th class="sortable links" col="links">Links</th></tr> |
| | | <tr hidden="true" id="not-found-message"> |
| | | <th colspan="4">No results found. Try to check the filters</th></tr></thead> |
| | | <tbody class="passed results-table-row"> |
| | | <tr> |
| | | <td class="col-result">Passed</td> |
| | | <td class="col-name">testcase/test_smoking.py::TestSmoking::test_login</td> |
| | | <td class="col-duration">4.52</td> |
| | | <td class="col-links"></td></tr> |
| | | <tr> |
| | | <td class="extra" colspan="4"> |
| | | <div class="empty log">No log output captured.</div></td></tr></tbody> |
| | | <tbody class="passed results-table-row"> |
| | | <tr> |
| | | <td class="col-result">Passed</td> |
| | | <td class="col-name">testcase/test_smoking.py::TestSmoking::test_create_package</td> |
| | | <td class="col-duration">8.38</td> |
| | | <td class="col-links"></td></tr> |
| | | <tr> |
| | | <td class="extra" colspan="4"> |
| | | <div class="empty log">No log output captured.</div></td></tr></tbody> |
| | | <tbody class="passed results-table-row"> |
| | | <tr> |
| | | <td class="col-result">Passed</td> |
| | | <td class="col-name">testcase/test_smoking.py::TestSmoking::test_open_url</td> |
| | | <td class="col-duration">6.30</td> |
| | | <td class="col-links"></td></tr> |
| | | <tr> |
| | | <td class="extra" colspan="4"> |
| | | <div class="empty log">No log output captured.</div></td></tr></tbody> |
| | | <tbody class="passed results-table-row"> |
| | | <tr> |
| | | <td class="col-result">Passed</td> |
| | | <td class="col-name">testcase/test_smoking.py::TestSmoking::test_answer</td> |
| | | <td class="col-duration">46.21</td> |
| | | <td class="col-links"></td></tr> |
| | | <tr> |
| | | <td class="extra" colspan="4"> |
| | | <div class="empty log">No log output captured.</div></td></tr></tbody></table></body></html> |
New file |
| | |
| | | from datetime import datetime |
| | | import multiprocessing |
| | | import threading |
| | | import time |
| | | |
| | | import pytest |
| | | from selenium import webdriver |
| | | from selenium.webdriver.chrome.options import Options |
| | | from po.login_page import LoginPage |
| | | from po.home_page import HomePage |
| | | from po.test_package_list_page import TestPackageListPage |
| | | from po.share_add_page import ShareAddPage |
| | | from po.answer_page import AnswerPage |
| | | from comm.my_random import * |
| | | from selenium.common import WebDriverException |
| | | from selenium.common.exceptions import ElementClickInterceptedException, TimeoutException |
| | | import HTMLTestRunner |
| | | |
| | | |
| | | class TestSmoking: |
| | | driver = None |
| | | test_package_name = "MAQ自动测试包-20230711151825" |
| | | |
| | | def test_login(self): |
| | | """ |
| | | 打开页面并进行登录测试 |
| | | :return: |
| | | """ |
| | | TestSmoking.driver = webdriver.Chrome() |
| | | driver = TestSmoking.driver |
| | | login_page = LoginPage(driver) |
| | | driver.get("http://47.114.179.216:8090/login?lang=zh_CN") |
| | | driver.maximize_window() |
| | | login_page.login("admin", "HyNc#jp0z#N7Y5ih", "ots") |
| | | time.sleep(2) |
| | | assert login_page.is_login_success() |
| | | |
| | | def test_create_package(self): |
| | | """ |
| | | 创建测试包 |
| | | :return: |
| | | """ |
| | | # 获取driver |
| | | driver = TestSmoking.driver |
| | | # 创建home页面的对象 |
| | | home_page = HomePage(driver) |
| | | # 点击左侧菜单进入页面 |
| | | home_page.menu_select("测试包管理/测试包列表") |
| | | |
| | | # 创建测试包列表页面的对象 |
| | | test_package_list = TestPackageListPage(driver) |
| | | # 点击创建按钮 |
| | | test_package_list.create_btn() |
| | | # 获取当前时间 |
| | | current_time = datetime.now() |
| | | # 转换为字符串 |
| | | time_str = current_time.strftime("%Y%m%d%H%M%S") |
| | | # 创建测试包填写的参数 |
| | | # 测试包名称 |
| | | test_package_name = "MAQ自动测试包-" + time_str |
| | | # 设置测试包名称为类变量 |
| | | TestSmoking.test_package_name = test_package_name |
| | | # 报告企业名称 |
| | | report_company_name = "TAI测试" |
| | | # 测试包类型 |
| | | test_package_type = "人格测试包" |
| | | # 产品包 |
| | | prod_name = "MAQV2" |
| | | # HR邮箱 |
| | | hr_email = "2077506045@qq.com" |
| | | # 有效期 |
| | | invalid_time = "2024-01-01 00:00:00" |
| | | # 测试者邀请邮件语言类型 |
| | | test_email_lang_type = "中文" |
| | | # hr报告邮件语言类型 |
| | | hr_report_email_lang_type = "中文" |
| | | # 报告模板 |
| | | report_template = "MAQV2-Complete-Chinese" |
| | | # 测试者报告邮件语言类型 |
| | | member_report_email_lang_type = "中文" |
| | | |
| | | # 填写测试包名称 |
| | | test_package_list.testPackageName_input(test_package_name) |
| | | # 填写报告企业名称 |
| | | test_package_list.reportCompanyName_input(report_company_name) |
| | | # 选择测试包类型 |
| | | test_package_list.testPackageType_select(test_package_type) |
| | | # 选择产品包 |
| | | test_package_list.prodTree_select(prod_name) |
| | | # 输入hr邮箱 |
| | | test_package_list.hrReportEmail_input(hr_email) |
| | | # 输入有效期 |
| | | test_package_list.invalidTime_input(invalid_time) |
| | | # 选择邀请邮件语言类型 |
| | | test_package_list.testTemplateLangType_select(test_email_lang_type) |
| | | # 选择HR邮件语言类型 |
| | | test_package_list.hrTemplateLangType_select(hr_report_email_lang_type) |
| | | # 选择报告模板 |
| | | test_package_list.reportTemplate_select(report_template) |
| | | # 点击测试者接收报告 |
| | | test_package_list.autoSendReport_checkbox() |
| | | # 选择测试者报告邮箱语言类型 |
| | | test_package_list.memberReportLangType_select(member_report_email_lang_type) |
| | | # 点击确认按钮 |
| | | test_package_list.add_confirm() |
| | | time.sleep(2) |
| | | # 判断是否成功创建 |
| | | assert test_package_list.is_create_success(test_package_name) |
| | | |
| | | def test_open_url(self): |
| | | """ |
| | | 打开分享链接 |
| | | :return: |
| | | """ |
| | | # 获取driver |
| | | driver = TestSmoking.driver |
| | | # 创建home页面的对象 |
| | | # home_page = HomePage(driver) |
| | | # 点击左侧菜单进入页面 |
| | | # home_page.menu_select("测试包管理/测试包列表") |
| | | # 创建测试包列表页面的对象 |
| | | test_package_list = TestPackageListPage(driver) |
| | | # 勾选新创建的测试包 |
| | | test_package_list.click_package_checkbox(TestSmoking.test_package_name) |
| | | # 点击生成分享链接按钮 |
| | | test_package_list.click_share_1_btn() |
| | | # 获取到url |
| | | url = test_package_list.get_share_url() |
| | | # 打开新标签页加载url |
| | | test_package_list.open_new_table_to_url(url) |
| | | # 创建分享页面对象 |
| | | share_add = ShareAddPage(driver) |
| | | # 填写信息提交并获取测试链接 |
| | | name = random_string(8) |
| | | email = name + "@gmail.com" |
| | | test_url = share_add.page_default_operation(name, email) |
| | | # test_url = "http://161.117.57.194/exam-stu/#/ots/94830ada-8f6c-44c0-8946-79c43267d9c1/login" |
| | | # 当前页面打开链接 |
| | | driver.get(test_url) |
| | | # 点击提交按钮 |
| | | share_add.submit_btn() |
| | | # 填写基本信息并提交 |
| | | share_add.fill_info(email, "职员", "人事部") |
| | | # 点击开始测试 |
| | | share_add.submit_btn() |
| | | |
| | | def test_answer(self): |
| | | # 获取driver |
| | | driver = TestSmoking.driver |
| | | # 创建answer对象 |
| | | answer_page = AnswerPage(driver) |
| | | # 开始答题 |
| | | answer_page.answer_MAQ() |
| | | # 答完题关闭当前标签页 |
| | | driver.close() |
| | | # 切换到第一个标签页 |
| | | answer_page.switch_window(0) |
| | | # 创建测试包列表页面的对象 |
| | | test_package_list = TestPackageListPage(driver) |
| | | # 删除测试包 |
| | | test_package_list.delete_package() |
| | | time.sleep(5) |
| | | # 关闭 |
| | | driver.quit() |
| | | |
| | | |
| | | if __name__ == '__main__': |
| | | pytest.main(["-s", __file__]) |