一、下载及安装插件
python
selenium
pytest
allure
辅助:pyautoit pymysql
二、代码框架
1、基础文件
[main.py]
if __name__ == '__main__': pytest.main(["--alluredir", "./alluretmp"]) # pytest.main() os.system("allure generate ./alluretmp -o ./allure-report --clean")
[pytest.ini]
[pytest] addopts = -vs -rerun=2 ;addopts = -vs testpaths = ./testcase python_files = test*.py python_classes =Test* python_functions = test_* markers = smoke story: sdv sit: sit uat: uat
[conftest.py]
import time import allure import pytest import os from selenium import webdriver from common.path import Path from common.getFileDatas import GetFileDatas from page.login.loginpage import LoginPage driver = None @pytest.fixture(scope='session', autouse=True) def clean_tmp_allure(): tmp_allure_path = Path().get_project_path() + r'\alluretmp' tmpallure_files = os.listdir(tmp_allure_path) for fl in tmpallure_files: fl_path = tmp_allure_path + "\\" + fl if fl.endswith(".json") or fl.endswith(".txt"): os.remove(fl_path) @pytest.fixture(scope='class') def start_login(): global driver # if driver is None: # driver = webdriver.Chrome() driver = webdriver.Chrome() index_url = GetFileDatas().get_ini_data_bypath_section(Path().get_project_path() + r'\config\env.ini', 'test_env')[ 'testurl'] login_url = '/user/login' LoginPage(driver).login(index_url + login_url, GetFileDatas().get_ini_data_bypath_section(Path().get_project_path() + r'\config\env.ini', 'user_info')[ 'username'], GetFileDatas().get_ini_data_bypath_section(Path().get_project_path() + r'\config\env.ini', 'user_info')[ 'pwd']) yield driver driver.quit() # 调试无头模式,还未ok # @pytest.fixture(scope='class') # def start_driver(): # """是否启用headless""" # chrome_option = Options() # if GetFileDatas().get_ini_data_bypath_section(Path().get_project_path() + r'\config\env.ini', 'selenium')[ # 'headless']: # chrome_option.add_argument('--headless') # chrome_option.add_argument('--disable-software-rasterizer') # driver = webdriver.ChromeOptions(options=chrome_option) # yield driver # driver.quit() """ 控制台用例名称乱码""" def pytest_collection_modifyitems(items): print("收集到的所有测试用例{}".format(items)) for item in items: item.name = item.name.encode("utf-8").decode("unicode_escape") item._nodeid = item.nodeid.encode("utf-8").decode("unicode_escape") @pytest.hookimpl(tryfirst=True, hookwrapper=True) def pytest_runtest_makereport(item, call): """ 获取每个用例的钩子函数 :param item: :param call: :return: """ outcome = yield rep = outcome.get_result() # 以下为实现异常截图的代码: # rep.when可选参数有call、setup、teardown, # call表示为用例执行环节、setup、teardown为环境初始化和清理环节 # 这里只针对用例执行且失败的用例进行异常截图 if rep.when == "call" and rep.failed: mode = "a" if os.path.exists("failures") else "w" with open("failures", mode) as f: if "tmpdir" in item.fixturenames: extra = " (%s) " % item.funcargs["tmpdir"] else: extra = "" f.write(rep.nodeid + extra + "\n") item.name = item.name.encode("utf-8").decode("unicode-escape") file_name = '{}.png'.format(str(round(time.time() * 1000))) path = os.path.join(Path().get_project_path()+r'\alluretmp', file_name) driver.save_screenshot(path) if hasattr(driver, "get_screenshot_as_png"): with allure.step("添加失败截图"): # get_screenshot_as_png实现截图并生成二进制数据 # allure.attach直接将截图二进制数据附加到allure报告中 allure.attach(driver.get_screenshot_as_png(), "失败截图", allure.attachment_type.PNG) if __name__ == '__main__': pass
[common/basepage.py]
import time import autoit from selenium.webdriver import Keys from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.remote.webdriver import WebDriver from selenium.webdriver.support.select import Select class BasePage: def __init__(self, driver): self.driver = driver def visit(self, url): self.driver.get(url) self.driver.maximize_window() time.sleep(1) def locator(self, loc): return WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located(loc)) def get_ele_isvisibility(self, loc): return self.locator(loc).is_displayed() def get_ele_isexist(self, loc): try: self.locator(loc) return True except: return False def input(self, loc, txt): self.locator(loc).send_keys(txt) """"清空textarea文本域的内容""" def clear(self, loc): self.locator(loc).clear() """通过键盘事件,清空input输入框的内容""" def clear_input(self, loc): self.locator(loc).send_keys(Keys.CONTROL, 'A') self.locator(loc).send_keys(Keys.DELETE) """ 针对下拉选择框定位,引用select类""" def select_by_value(self,loc,value): Select(self.locator(loc)).select_by_value(value) @staticmethod def execute_script(script1): WebDriver().execute_script(script=script1) def click(self, loc): self.locator(loc).click() def wait(self, time_): time.sleep(time_) def quit(self): self.driver.quit() def close_return_Home(self): self.driver.close() home_page = self.driver.window_handles[0] self.driver.switch_to.window(home_page) def get_ele_attr_value(self, loc, name): ele = self.locator(loc) return ele.get_attribute(name) """ 鼠标悬停事件""" def move_to_element(self, loc): ActionChains(self.driver).move_to_element(self.locator(loc)).perform() """ 获取页面元素的内容""" def get_page_ele_txt(self, loc): return self.locator(loc).text """校验某一个button按钮是否disable""" def get_ele_isdisable(self, loc): return self.locator(loc).is_enabled() """获取表格中某一单元格的值 """ def get_table_cell_value(self, loc): return self.locator(loc).text def click_table_cell_btn(self, loc): self.locator(loc).click() """ 获取表格中某一单元格的值""" def check_table_cell_value(self, loc, row, col): cell_loc = (loc[0], loc[1] + "/tr[" + str(row) + "]" + "/td[" + str(col) + "]") return self.locator(cell_loc).text """判断某元素是否置灰""" def check_element_isenable(self, loc): return self.locator(loc).is_enabled """alert弹框,只有一个确定按钮 1、点击确定 2、获取alert弹框的内容""" def switch_to_alert_comfirm(self): time