一、下载及安装插件
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.sleep(1)
self.driver.switch_to_alert.accept()
def swithch_to_alert_dismiss(self):
time.sleep(1)
self.driver.switch_to_alert.dismiss()
def get_switch_to_alert_text(self):
time.sleep(2)
return self.driver.switch_to.alert.text
def switch_to_window(self):
return self.driver.switch_to.window('打开')
"""鼠标当前位置偏移量"""
def mouse_move_to_ele(self, loc, xoffset, yoffset):
ActionChains(self.driver).move_to_element(self.locator(loc)).move_by_offset(xoffset,
yoffset).release().click().perform()
"""鼠标拖动"""
def mouse_drag_and_drop_ele(self, source_ele, target_ele):
ActionChains(self.driver).drag_and_drop(self.locator(source_ele), self.locator(target_ele))
""" 切换到新的window窗口"""
def swith_to_new_window(self):
new_window = self.driver.window_handles[-1]
self.driver.switch_to.window(new_window)
# new_window = WebDriver().window_handles[-1]
# WebDriver().switch_to.window(new_window)
""" 使用autoit处理window系统框
STEP1: 获取输入框焦点,输入文件url
STEP2: 点击打开文件,并再次输入文件名
STEP3: 点击打开,弹出框小时"""
@staticmethod
def select_window_alert_files(file_path, files):
time.sleep(1)
autoit.control_focus("打开", "[CLASS:Edit; INSTANCE:1]")
autoit.control_set_text("打开", "[CLASS:Edit; INSTANCE:1]", file_path)
time.sleep(2)
autoit.control_click("打开", "[Class:Button; instance:1]")
time.sleep(2)
autoit.control_set_text("打开", "[CLASS:Edit; INSTANCE:1]", files)
time.sleep(2)
autoit.control_click("打开", "[Class:Button; instance:1]")
time.sleep(2)
"""还有针对alert弹框点击确认,取消操作的方法封装
还有切换iframe
返回到主窗口
"""
[common/const.py]
from common.getFileDatas import GetFileDatas
from common.path import Path
class Const:
def __init__(self):
self.user_info = GetFileDatas().get_ini_data_bypath_section(Path().get_project_path() + r'\config\env.ini', 'user_info')
self.base_url = GetFileDatas().get_ini_data_bypath_section(Path().get_project_path() + r'\config\env.ini', 'test_env')['testurl']
self.base_test_datas_path = GetFileDatas().get_ini_data_bypath_section(Path().get_project_path() + r'\config\env.ini', 'test_data_path')['path']
self.mysql_info = GetFileDatas().get_ini_data_bypath_section(Path().get_project_path() + r'\config\env.ini','mysql')
self.normal_role = GetFileDatas().get_ini_data_bypath_section(Path().get_project_path() + r'\config\env.ini','role_rule')['normal_role']
self.admin_role = GetFileDatas().get_ini_data_bypath_section(Path().get_project_path() + r'\config\env.ini', 'role_rule')['admin_role']
[common/dbconn.py]
import pymysql
class Dbconn(object):
def __init__(self, dbinfo):
self.db = pymysql.connect(cursorclass=pymysql.cursors.DictCursor, **dbinfo)
self.cursor = self.db.cursor()
def query_data(self, sql):
try:
self.cursor.execute(sql)
return self.cursor.fetchall()
except Exception as e:
print(e)
def execute_sql(self,sql):
try:
self.cursor.execute(sql)
self.db.commit()
except Exception as e:
print(e)
def close(self):
self.cursor.close()
self.db.close()
[common/getFileDatas.py]
import yaml
import configparser
class GetFileDatas:
@staticmethod
def get_yml_data_bypath(path):
try:
with open(path, 'r', encoding='utf-8') as f:
data = yaml.load(stream=f, Loader=yaml.FullLoader)
return data
except Exception as e:
print('get yml data failure,reason is :{}'.format(e))
@staticmethod
def get_ini_data_bypath_section(path, section):
try:
_configparser = configparser.ConfigParser()
_configparser.read(path, encoding='utf-8')
options = _configparser.options(section)
value_lst = {}
for option in options:
value = _configparser.get(section, option)
if option not in value_lst:
value_lst[option] = value
return value_lst
except Exception as e:
print('get ini data failure,reason is:{}'.format(e))
if __name__ == '__main__':
test_get_data = GetFileDatas()
# print(test_get_data.get_yml_data_bypath(r'E:\py\test\testdata\loginYml.yml'))
print(test_get_data.get_ini_data_bypath_section(r'env.ini', 'mysql'))
[common/logger.py]
import logging
import os.path
from common.path import Path
class Logger:
def __init__(self,name):
self.logger = logging.getLogger(name)
self.logger.setLevel(logging.DEBUG)
self.project_path = Path().get_project_path()
def get_logger(self):
hander = logging.FileHandler(filename=self.project_path+'/logs/log.log',encoding='utf-8')
hander.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
hander.setFormatter(formatter)
self.logger.addHandler(hander)
return self.logger
[common/path.py]
import os
class Path:
@staticmethod
def get_project_path():
return os.path.dirname(os.path.abspath(os.path.dirname(__file__)))
if __name__ == '__main__':
print(Path().get_project_path())
[common/update_db_data.py]
import time
from common.const import Const
from common.dbconn import Dbconn
from common.getFileDatas import GetFileDatas
class Update_Db_Data:
@staticmethod
def get_my_sql_info():
mysql_info = Const().mysql_info
mysql_info["port"] = int(mysql_info["port"])
return mysql_info
def update_status(self, patient_name, study_status, study_realgin_status, series_dx_status):
5
"""
try:
update_study_sql = f'update t_study ts set ts.status ={study_status},ts.update_dt = SYSDATE() where exists \
(select 1 from t_patient tt where tt.id= ts.patient and tt.patient_name =\'{patient_name}\')'
update_study_realign_sql = f'update t_study_realign ts set ts.request_status ={study_realgin_status},ts.update_dt = ' \
f'SYSDATE() where exists (select 1 from t_patient tt,t_study tst where tt.id= ' \
f'tst.pati' \
f'ent and tst.id = ts.study and tt.patient_name =\'{patient_name}\') '
update_series_sql = f'update t_series_dx tsd set tsd.request_status = {series_dx_status}, tsd.request_dt ' \
f'= SYSDATE() where EXISTS( select 1 from t_patient tp where tsd.patient = tp.id and ' \
f'tp.patient_name = \'{patient_name}\') '
db = Dbconn(self.get_my_sql_info())
db.execute_sql(update_study_sql)
db.execute_sql(update_study_realign_sql)
if series_dx_status != '':
db.execute_sql(update_series_sql)
db.close()
time.sleep(1)
except Exception as e:
print(e)
def delete_user_account(self, username):
delete_user_data_sql1 = f'delete from t_user_role where user IN(select id from t_user tu where tu.username = \'{username}\' )'
delete_user_data_sql2 = f'delete from t_user where username =\'{username}\''
db = Dbconn(self.get_my_sql_info())
db.execute_sql(delete_user_data_sql1)
db.execute_sql(delete_user_data_sql2)
db.close()
[config/env.ini]
[test_env]
testurl =
[user_info]
username =
pwd =
[mysql]
host =
port =
user =
password =
database =
[test_data_path]
path = E:\autotest\ais_ui_testdatas
[selenium]
headless = True
thread_num = 1
[role_rule]
normal_role =
admin_role =
[page/login/loginpage.py]
import time
import allure
from selenium.webdriver.common.by import By
from common.basepage import BasePage
from selenium import webdriver
from common.logger import Logger
class LoginPage(BasePage):
logger = Logger('LoginPage').get_logger()
username = (By.ID, "username")
password = (By.ID, "password")
login_btn = (By.XPATH, '//*[@id="root"]/div/div[3]/div[1]/div[2]/form/button')
"""登录成功/失败后的页面告警page元素"""
login_success_page = (By.XPATH, '/html/body/div[2]/div/div/div/div/div')
login_fail_page = (By.XPATH, '/html/body/div[2]/div/div/div/div/div/div[1]')
username_error_msg = (By.XPATH, '//*[@id="root"]/div/div[3]/div[1]/div[2]/form/div[2]/div/div[2]/div')
password_error_msg = (By.XPATH, '//*[@id="root"]/div/div[3]/div[1]/div[2]/form/div[3]/div/div[2]/div')
"""icon"""
username_close_circle = (By.XPATH, '//*[@id="root"]/div/div[3]/div[1]/div[2]/form/div[2]/div/div/div/span/span['
'2]/span')
password_eye = (By.XPATH, '//*[@id="root"]/div/div[3]/div[1]/div[2]/form/div[3]/div/div/div/span/span[2]/span')
"""退出登录模块"""
account_name_ele = (By.XPATH, '//*[@id="root"]/div/section/div[2]/header[2]/div/div[3]/div[2]/span/span[2]')
login_out_btn = (By.XPATH, '/html/body/div[3]/div/div/ul/li[3]/span')
def login(self, url, username, pwd):
self.logger.debug("进入登录页面:{}".format(url))
with allure.step("进入登录页面:{}".format(url)):
time.sleep(1)
self.visit(url)
self.logger.debug("输入用户名:{} 密码:{}".format(username if username else '为空', pwd if pwd else '为空'))
with allure.step("输入用户名:{} 密码:{}".format(username if username else '为空', pwd if pwd else '为空')):
time.sleep(1)
self.input(self.username, username)
self.input(self.password, pwd)
self.logger.debug("点击登录按钮")
with allure.step("点击登录按钮"):
time.sleep(1)
self.click(self.login_btn)
time.sleep(1)
def login_out(self):
with allure.step("鼠标悬停至软件右上角用户真实姓名处"):
time.sleep(2)
self.move_to_element(self.account_name_ele)
time.sleep(1)
with allure.step("点击退出登录按钮"):
self.click(self.login_out_btn)
def check_login_out_issuccess(self,expected_result):
assert expected_result == self.get_ele_isvisibility(self.login_btn)
def get_page_msg(self, loc):
return self.get_page_ele_txt(loc)
def check_page_msg(self, loc, exep_txt):
actual_page_msg = self.get_page_ele_txt(loc)
assert actual_page_msg == exep_txt
def check_sucesspage_msg(self, exep_txt):
assert self.get_page_msg(LoginPage.login_success_page) == exep_txt
def check_failurepage_msg(self, exep_txt):
assert self.get_page_ele_txt(LoginPage.login_fail_page) == exep_txt
def check_username_error(self, exep_txt):
assert self.get_page_ele_txt(LoginPage.username_error_msg) == exep_txt
def check_password_error(self, exep_txt):
assert self.get_page_ele_txt(LoginPage.password_error_msg) == exep_txt
[testcase/login/testlogin.py]
import allure
import pytest
from selenium import webdriver
from common.const import Const
from common.logger import Logger
from common.path import Path
from page.login.loginpage import LoginPage
from testdata.login import loginpage_datas
@allure.parent_suite("系统登录页面")
@allure.epic("系统登录")
class TestLoginPage:
test_url = Const().base_url
logger = Logger("TestLoginPage").get_logger()
def setup(self):
self.driver = webdriver.Chrome()
self.lp = LoginPage(self.driver)
def teardown(self):
self.driver.quit()
@allure.feature("系统登录")
@allure.story("登录成功场景")
@pytest.mark.parametrize('data', loginpage_datas.login_sucess,
ids=[i['case_name'] for i in loginpage_datas.login_sucess])
def test_login_success(self, data):
username, pwd = data['username'], data['password']
expected_results = data['expected_results']
url = self.test_url + '/user/login'
self.lp.login(url, username, pwd)
self.logger.debug('校验实际结果是否为:{}'.format(expected_results))
with allure.step('校验实际结果是否为:{}'.format(expected_results)):
self.lp.check_sucesspage_msg(expected_results)
@allure.feature("系统登录")
@allure.story("登录失败场景")
@pytest.mark.parametrize('data', loginpage_datas.login_failure,
ids=[i['case_name'] for i in loginpage_datas.login_failure])
def test_login_failure(self, data):
username, pwd = data['username'], data['password']
expected_results = data['expected_results']
url = self.test_url + '/user/login'
self.lp.login(url, username, pwd)
self.logger.debug('校验实际结果是否为:{}'.format(expected_results))
with allure.step('校验实际结果是否为:{}'.format(expected_results)):
self.lp.check_failurepage_msg(expected_results)
@allure.feature("系统登录")
@allure.story("登录异常场景")
@pytest.mark.parametrize('data', loginpage_datas.login_exception,
ids=[i['case_name'] for i in loginpage_datas.login_exception])
def test_login_exception(self, data):
self.logger.debug("........debug log testing 1.....")
username, pwd = data['username'], data['password']
expected_results = data['expected_results']
url = self.test_url + '/user/login'
self.lp.login(url, username, pwd)
self.logger.debug("........debug log testing 2.....")
self.logger.debug('校验实际结果是否为:{}'.format(expected_results))
with allure.step('校验实际结果是否为:{}'.format(expected_results)):
try:
if data['username'] == '':
self.lp.check_username_error(expected_results)
else:
self.lp.check_password_error(expected_results)
except:
self.logger.error("........error log testing .....")
@allure.feature("系统退出")
@allure.story("登录退出")
@pytest.mark.parametrize('data', loginpage_datas.login_out,
ids=[i['case_name'] for i in loginpage_datas.login_out])
def test_login_out(self, data):
username, pwd = data['username'], data['password']
expected_results = data['expected_results']
url = self.test_url + '/user/login'
self.lp.login(url, username, pwd)
self.lp.login_out()
with allure.step('校验实际结果是否为'.format(expected_results)):
self.lp.check_login_out_issuccess(expected_results)
if __name__ == '__main__':
pytest.main()
[testcase/login/study.py]
import time
import allure
import pytest
from common.const import Const
from common.logger import Logger
from common.update_db_data import Update_Db_Data
from page.ctp.ctppage import CtpPage
from page.studyupload.studyuploadpage import StudyUploadPage
from testdata.studylist import studylistpage_align_datas as slap, studylistpage_datas as slp, \
studylistpage_delete_datas as delp
from page.studylist.studylistpage import Studylist
@allure.parent_suite("影像列表")
@allure.epic("影像列表")
@pytest.mark.usefixtures("start_login")
class Teststudylist:
base_url, base_test_datas_path = Const().base_url, Const().base_test_datas_path
logger = Logger('Teststudylist').get_logger()
@allure.feature("列表查询")
@allure.story("正向查询")
@pytest.mark.parametrize('data', slp.search_conditions_ok, ids=[(i['case_name']) for i in slp.search_conditions_ok])
def test_study_search_Ok(self, data, start_login):
with allure.step("初始化影像列表页面:{}".format(Teststudylist.base_url + data['page_url'])):
study_lst_page = Teststudylist.base_url + data['page_url']
with allure.step("获取测试用例数据:{}".format(data['case_name'])):
search_data_tmp = data['search_conditions']
search_datas = []
for i in search_data_tmp:
search_datas.append(search_data_tmp[i])
expected_results = data['expected_results']
with allure.step("进入影像列表页面{}".format(study_lst_page)):
sl = Studylist(start_login)
sl.visit(study_lst_page)
with allure.step("查询影像"):
sl.search(search_datas)
with allure.step('校验CTP列表患者姓名是否等于{},列表列表总记录是否等于{}'.format(data['expected_results']['patient_name'],data['expected_results']['result_count'])):
sl.check_study_list_count(expected_results['result_count'])
sl.check_study_list_cell_value(1, 3, expected_results['patient_name'])
@allure.feature("列表查询")
@allure.story("反向查询")
@pytest.mark.parametrize('data', slp.search_conditions_nodata,
ids=[(i['case_name']) for i in slp.search_conditions_nodata])
def test_study_search_nodata(self, data, start_login):
with allure.step("初始化影像列表页面:{}".format(Teststudylist.base_url + data['page_url'])):
study_lst_page = Teststudylist.base_url + data['page_url']
with allure.step("获取测试用例数据:{}".format(data['case_name'])):
search_data_tmp = data['search_conditions']
search_datas = []
for i in search_data_tmp:
search_datas.append(search_data_tmp[i])
expected_results = data['expected_results']
with allure.step("进入影像列表页面{}".format(study_lst_page)):
sl = Studylist(start_login)
sl.visit(study_lst_page)
with allure.step("查询影像"):
sl.search(search_datas)
with allure.step("校验影像列表是否展示为{}".format(data['expected_results'])):
sl.check_study_list_nodata_cell(expected_results)
@allure.feature("影像校正")
@allure.story("校正成功场景")
@pytest.mark.parametrize('data', slap.align_ok, ids=[(i['case_name']) for i in slap.align_ok])
def test_study_align_success(self, data, start_login):
try:
with allure.step("初始化影像列表页面:{}".format(Teststudylist.base_url + data['page_url'])):
study_lst_page = Teststudylist.base_url + data['page_url']
with allure.step("获取测试用例数据:{}".format(data['case_name'])):
expected_results = data['expected_results']
search_data_tmp = data['search_conditions']
search_datas = []
for i in search_data_tmp:
search_datas.append(search_data_tmp[i])
with allure.step("进入影像列表页面{}".format(study_lst_page)):
sl = Studylist(start_login)
sl.visit(study_lst_page)
with allure.step("查询待校正的影像"):
sl.search(search_datas)
with allure.step("点击校正"):
sl.click_study_list_align_btn(1, 13)
time.sleep(1)
with allure.step("校验实际结果是否为已校正"):
time.sleep(180)
while sl.get_study_list_cell_value(1, 11) in ['校正中', '校正异常']:
time.sleep(10)
assert sl.get_study_list_cell_value(1, 11) == expected_results
except Exception as e:
self.logger.error(e)
finally:
with allure.step("恢复测试数据状态为{}".format(data['status'])):
Update_Db_Data().update_status(data['search_conditions']['patientname'], 0,0,'') if data['status'] in [
'未校正'] else Update_Db_Data().update_status(data['search_conditions']['patientname'], 2, 2,'') if \
data['status'] in ['已校正'] else 0
@allure.feature("影像校正")
@allure.story("不可校正场景")
@pytest.mark.parametrize('data', slap.align_no, ids=[(i['case_name']) for i in slap.align_no])
def test_study_align_faiure(self, data, start_login):
try:
with allure.step("初始化影像列表页面:{}".format(Teststudylist.base_url + data['page_url'])):
study_lst_page = Teststudylist.base_url + data['page_url']
with allure.step("获取测试用例数据:{}".format(data['case_name'])):
search_data_tmp = data['search_conditions']
search_datas = []
for i in search_data_tmp:
search_datas.append(search_data_tmp[i])
with allure.step("修改影像状态为{}".format(data['status'])):
Update_Db_Data().update_status(data['search_conditions']['patientname'], 1,1,'') if data['status'] in [
'校正中'] else Update_Db_Data().update_status(data['search_conditions']['patientname'], 3,2,3) if data[
'status'] in [
'分析中'] else 0
time.sleep(1)
with allure.step("进入影像列表页面{}".format(study_lst_page)):
sl = Studylist(start_login)
sl.visit(study_lst_page)
with allure.step("查询待校正的影像"):
sl.search(search_datas)
time.sleep(1)
with allure.step("校验当前影像所在行的校正按钮是否是否为:{}".format(data['expected_results'])):
sl.check_study_lst_align_btn_isenable(1, 13, data['expected_results'])
except Exception as e:
self.logger.error(e)
finally:
with allure.step("恢复测试数据"):
Update_Db_Data().update_status(data['search_conditions']['patientname'], 2, 2,'') if data['status'] in [
'校正中'] else Update_Db_Data().update_status(data['search_conditions']['patientname'], 4, 2,4) if data[
'status'] in [
'分析中'] else 0
@allure.feature("影像删除")
@allure.story("影像删除成功场景")
@pytest.mark.parametrize('data', delp.delete_success, ids=[(i['case_name']) for i in delp.delete_success])
def test_study_delete_success(self, data, start_login):
# driver = webdriver.Chrome()
# with allure.step("系统登录"):
# index = LoginPage(start_login)
# index.login(Teststudylist.base_url + data['login_url'], Teststudylist.user_info['username'],
# Teststudylist.user_info['pwd'])
with allure.step("初始化影像列表页面:{}".format(Teststudylist.base_url + data['page_url'])):
studypage = Studylist(start_login)
study_lst_page = Teststudylist.base_url + data['page_url']
with allure.step("进入影像上传页面,上传影像"):
upload_page = Teststudylist.base_url + data['upload_url']
up = StudyUploadPage(start_login)
up.visit(upload_page)
print('path:{}'.format(Teststudylist.base_test_datas_path + data['upload_datas']['file_path']))
up.upload_files_flow(Teststudylist.base_test_datas_path + data['upload_datas']['file_path'],
data['upload_datas']['files_name'])
time.sleep(1)
with allure.step("进入影像列表页面,并查询到需要删除的影像"):
studypage.visit(study_lst_page)
datas_tmp = data['search_conditions']
datas = []
for i in datas_tmp:
datas.append(datas_tmp[i])
print('data is {}'.format(datas))
studypage.search(datas)
time.sleep(1)
if data['status'] in ['已分析', '已校正']:
with allure.step('发起影像校正'):
studypage.click_study_list_align_btn(1, 13)
time.sleep(150)
while not studypage.get_study_list_cell_value(1, 11) in ['已校正', '校正异常']:
time.sleep(30)
if data['status'] in ['已分析']:
with allure.step('发起影像分析流程'):
ctp_page = Teststudylist.base_url + data['ctp_url']
ctp = CtpPage(start_login)
with allure.step("进入CTP页面,查询待分析影像"):
ctp.visit(ctp_page)
datas_tmp = data['search_conditions']
datas = []
for i in datas_tmp:
datas.append(datas_tmp[i])
ctp.search_flow(datas)
with allure.step("进入分析详情页选取动静脉点"):
ctp.analysis_flow(1, 13)
time.sleep(240)
with allure.step("返回至影像列表页、等待分析完成"):
studypage.visit(study_lst_page)
studypage.search(datas)
while studypage.get_study_list_cell_value(1, 11) not in ['分析异常', '已分析']:
time.sleep(10)
with allure.step("开始删除影像"):
studypage.click_study_list_del_btn(1, 13)
time.sleep(2)
studypage.click_study_lst_del_alert_ok_btn()
with allure.step("校验影像是否删除成功"):
studypage.click_search_btn()
studypage.check_study_list_nodata_cell(data['expected_results'])
@allure.feature("影像删除")
@allure.story("影像删除失败场景")
@pytest.mark.parametrize('data', delp.delete_failure, ids=[(i['case_name']) for i in delp.delete_failure])
def test_study_delete_failure(self, data, start_login):
try:
with allure.step("初始化影像列表页面"):
studypage = Studylist(start_login)
study_lst_page = Teststudylist.base_url + data['page_url']
with allure.step("修改影像状态为{}".format(data['status'])):
Update_Db_Data().update_status(data['search_conditions']['patientname'], 1,1,'') if data['status'] in [
'校正中'] else Update_Db_Data().update_status(data['search_conditions']['patientname'], 3,2,3) if data[
'status'] in [
'分析中'] else 0
time.sleep(1)
with allure.step("进入影像列表页面,并查询到需要删除的影像"):
studypage.visit(study_lst_page)
datas_tmp = data['search_conditions']
datas = []
for i in datas_tmp:
datas.append(datas_tmp[i])
studypage.search(datas)
time.sleep(1)
with allure.step("校验实际结果是否等于预期结果({})".format(data['expected_results'])):
studypage.check_study_lst_del_btn_isenable(1, 13, data['expected_results'])
except Exception as e:
self.logger.error(e)
finally:
with allure.step("恢复测试数据"):
Update_Db_Data().update_status(data['search_conditions']['patientname'], 2,2,'') if data['status'] in [
'校正中'] else Update_Db_Data().update_status(data['search_conditions']['patientname'], 4,2,4) if data[
'status'] in [
'分析中'] else 0
if __name__ == '__main__':
pytest.main()
[testdata/login/login_testdata.py]
# 登录成功场景
login_sucess = [
{ 'case_name': '用户名和密码正确、登录成功',
'username': 'ais',
'password': '123456',
'expected_results': '登录成功!'
}
]
# 登录失败场景
login_failure = [
{ 'case_name': '用户名正确、密码错误、登录失败',
'username': 'ais',
'password': '12323456',
'expected_results': '用户名或密码错误'
},
{ 'case_name': '用户不正确、登录失败',
'username': 'ais1',
'password': '123456',
'expected_results': '用户名或密码错误'
}
]
# 异常登录场景
login_exception = [
{'case_name': '用户名为空、登录失败',
'username': '',
'password': '12323456',
'expected_results': '用户名不能为空!'
},
{ 'case_name': '密码为空、登录失败',
'username': 'ais',
'password': '',
'expected_results': '密码不能为空!'
}
]
# 系统退出
login_out = [
{'case_name': '点击退出系统按钮、返回软件登录页',
'username': 'ais',
'password': '123456',
'expected_results': True #登录页的登录按钮可见
}
]