Base.py
#####
各公共方法的二次封装以及定义,如抛弃selenium最外层的定位方法,直接传入By类的变量,既避免过长的函数定义也规范了元素定位的变量定义;同时由于系统中部分控件用鼠标点击不好定位,不能灵活
的传参,所以根据控件类型封装各type_xx函数,调用js来替代原生方法;考虑到代码的运行速度远高于浏览器的渲染速度以及网络加载速度,在隐式等待30秒的基础上,基类中的定位方法在操作前都设置强制等待
0.2s的时间,避免page页中的每个操作后都加强制等待时间的繁琐
-*- coding:utf8 -*- #Create on : 2017 - 04 -24 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.common.by import By from selenium.common.exceptions import WebDriverException from selenium.common.exceptions import StaleElementReferenceException from selenium.common.exceptions import NoSuchElementException import logging import requests import re import time console = logging.StreamHandler() logging.basicConfig( level=logging.INFO, format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', datefmt='%Y-%m-%d %H:%M:%S', filename='log.log', filemode='w' ) console.setLevel(logging.INFO) formatter = logging.Formatter('%(message)s') console.setFormatter(formatter) logging.getLogger('').addHandler(console) def log(func): def wrapper(*args, **kwargs): info = func.__doc__ logging.info('testing at : %s' % info) return func(*args, **kwargs) return wrapper def errorLog(func): def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except: logging.getLogger().exception('Exception') exit() return wrapper def consoleLog(info,level = 'INFO'): if level is 'INFO' : logging.info(info) elif level is 'WARNING': logging.warning(info) elif level is 'ERROR': logging.error(info) class Base(object): """ BasePage封装所有页面都公用的方法,例如driver, url ,FindElement等 """ def __init__(self, selenium_driver): """ 实例化WebDriver对象 :rtype: object :param selenium_driver: WebDriver对象 """ self.driver = selenium_driver succeed = 0 #用来接受每个新增函数执行成功并创建数据的数量,每成功一个就自增1,大于0的情况下,在测试结束或者报错后根据值去删除对应的已生成的数据 testCondition = ('test','mock','trunk') #待测试环境:测试、预发、线上 test = testCondition[0] @errorLog def open(self,url,loc,havaFrame = True): """ 重写打开地址函数 :param url: 目标地址 :param loc: 接收一个By对象的元组,用以确认页面加载完成 :param havaFrame:是否有frame,默认为有(目前项目中页面基本都存在frame),切换至最近的一个frame """ self.driver.get(url) if havaFrame == True: self.switch_frame(0) WebDriverWait(self.driver, 30).until(EC.presence_of_element_located(loc)) self.driver.maximize_window() # def repeat(self,func,*param): # for i in range(0,10): # try: # func(param) # break # except: # time.sleep(1) @errorLog def staleness_of(self,loc,index = None): """ 此方法主要适用情况如合同初审后,需要再次双击列表页打开进行复审的操作。 初审后有一个提示成功的对话框和panel关闭的延迟,视解析和网络情况导致时间不定,此时若马上去双击会报StaleElementReferenceException,所以在此显示等待 """ if type(index) == int: eles = self.find_elements(index, *loc) WebDriverWait(self.driver, 30).until(EC.staleness_of(eles)) else: ele = self.find_element(*loc) WebDriverWait(self.driver, 30).until(EC.staleness_of(ele)) @errorLog def wait_element(self,loc): """ 等待目标元素出现 :param loc: 接收一个By对象的元组,用以确认页面加载完成 """ WebDriverWait(self.driver, 10).until(EC.presence_of_element_located(loc),message=u'等待元素未出现,请查看截图') time.sleep(1) @errorLog def find_element(self,*loc): """ 返回单个元素定位 """ WebDriverWait(self.driver,30).until(EC.visibility_of_element_located(loc)) return self.driver.find_element(*loc) @errorLog def find_elements(self,index,*loc): """ 返回多个元素定位 :param index: 定位目标为数组时,需指定所需元素在数组中的位置 """ WebDriverWait(self.driver,30).until(EC.visibility_of_element_located(loc)) return self.driver.find_elements(*loc)[index] @errorLog def check_submit(self): """ 等待提交完成的提示出现,如新增或修改数据后的保存成功等提示,以确认数据正常插入或更新。目前所有界面的提示存在时长为3s,所以等待3s PS:一开始加这么长时间的硬性等待,我是拒绝的,但后面发现很多界面的操作必须要等待这个提示完全消失才可以,我尝试了各种办法也做不到完全避免,所以妥协了,硬等待就硬等待吧 :param loc: 提示的元素定位 """ loc = (By.CSS_SELECTOR, '.bootstrap-growl.alert.alert-info.alert-dismissible') WebDriverWait(self.driver,30).until(EC.presence_of_element_located(loc),u'没有找到提交成功记录') time.sleep(3) @errorLog def input_text(self, loc, text,first=True,index = None): """ 重写send_keys方法 :param loc:目标元素 :param text:输入值 :param first:默认为输入框无内容,为False时则先清空再输入 :param index:定位目标为数组时,需指定所需元素在数组中的位置 """ if first: if type(index) == int: eles = self.find_elements(index,*loc) for i in range(0,10): try: eles.click() break except WebDriverException: time.sleep(1) eles.send_keys(text) else: ele = self.find_element(*loc) for i in range(0, 10): try: ele.click() break except WebDriverException: time.sleep(1) ele.send_keys(text) else: if type(index) == int: eles = self.find_elements(index,*loc) for i in range(0, 10): try: eles.click() break except WebDriverException: time.sleep(1) eles.clear() eles.send_keys(text) else: ele = self.find_element(*loc) for i in range(0, 10): try: ele.click() break except WebDriverException: time.sleep(1) ele.clear() ele.send_keys(text) @errorLog def click(self, loc,index = None): """ 重写click方法 :param index: 默认为定位单个元素点击,如定位返回数组,则调用多个元素定位方法 """ #WebDriverWait(self.driver,10).until(EC.element_to_be_clickable(loc),u'元素不可点击') if type(index) == int: eles = self.find_elements(index,*loc) for i in range(0,10): try: eles.click() break except WebDriverException: time.sleep(1) else: ele = self.find_element(*loc) for i in range(0,10): try: ele.click() break except WebDriverException: time.sleep(1) @errorLog def dblclick(self,loc,index = None,checkLoc = None): """ 重写双击方法 :param loc: 可执行双击的元素 (注:需核实元素是否有双击事件,如定位到tr中的某一个td时,双击是无效的,对tr的双击才有效。 是否有效,可在chrome的console中验证,如$('#test').dblclick() :param index:默认为定位单个元素点击,如定位返回数组,则调用多个元素定位方法 :param checkLoc:传递一个打开后的界面中的元素,用以确认双击成功打开详情页 """ if type(index) == int: for i in range(0,10): eles = self.find_elements(index, *loc) try: ActionChains(self.driver).double_click(eles).perform() if checkLoc != None: for i in range(0,10): try: self.driver.find_element(*checkLoc) break except NoSuchElementException: ActionChains(self.driver).double_click(eles).perform() break except StaleElementReferenceException: time.sleep(1) else: for i in range(0,5): ele = self.find_element(*loc) try: ActionChains(self.driver).double_click(ele).perform() if checkLoc != None: for i in range(0,10): try: self.driver.find_element(*checkLoc) break except NoSuchElementException: e = self.find_element(*loc) ActionChains(self.driver).double_click(e).perform() break except StaleElementReferenceException: time.sleep(1) @errorLog def context_click(self,loc,index = None): """ 重写右击方法 :param loc: 可执行右击的元素 :param index: 默认为定位单个元素点击,如定位返回数组,则调用多个元素定位方法 """ if type(index) == int: eles = self.find_elements(index,*loc) ActionChains(self.driver).context_click(eles).perform() else: ele = self.find_element(*loc) ActionChains(self.driver).context_click(ele).perform() @errorLog def switch_frame(self, loc): return self.driver.switch_to_frame(loc) @errorLog def script(self, js): """ 尽量少用js,因为执行速度远远高于网络和系统反应速度,很容易报错。 迫不得已用到js的情况下无外乎点击、传值等,如果太快页面没刷新过来会导致报WebDriverException(目前已知会报出WebDriverException),此处捕获后,等待1秒再次执行js,最多十次,若执行成功则跳出循环 :param js: :return: """ for i in range(1,11): try: self.driver.execute_script(js) break except WebDriverException,e: consoleLog(e) info = 'js执行失败,正进行第%s次尝试' % i consoleLog(info,level='WARNING') time.sleep(1) @errorLog def solr(self,core,condition,searchKey=None,searchValue=None): """ 测试完成后,目前是直接删除数据,apartment和house的solr中的数据也需删除 :param core: 需要删除的core,如apartment-core、house-core :param condition: 当前环境,如test、mock、trunk :param searchKey: 查询需要删除的数据ID的条件,如residential_name,house_code等,做增量操作时,无需传值 :param searchValue: 查询需要删除的数据ID的条件,对应searchKey,楼盘名称为test,房源编号为xxxxx,做增量操作时,无需传值 """ getKeyUrl = { 'house' : { 'test' : 'http://192.168.0.216:8080/solr/house_core/select?q=%s%%3A%s&fl=id&wt=json&indent=true&_=%s' % (searchKey,searchValue,str(time.time())), 'mock' : 'http://192.168.0.203:8080/solr/house_core/select?q=%s%%3A%s&fl=id&wt=json&indent=true&_=%s' % (searchKey,searchValue,str(time.time())), 'trunk' : 'http://121.40.105.35:8084/solr/house_core/select?q=%s%%3A%s&fl=id&wt=json&indent=true&_=%s' % (searchKey,searchValue,str(time.time())) }, 'apartment' : { 'test': 'http://192.168.0.216:8080/solr/apartment_core/select?q=%s%%3A%s&fl=id&wt=json&indent=true&_=%s' % (searchKey,searchValue,str(time.time())), 'mock' : 'http://192.168.0.203:8080/solr/apartment_core/select?q=%s%%3A%s&fl=id&wt=json&indent=true&_=%s' % (searchKey,searchValue,str(time.time())), 'trunk' : 'http://121.40.105.35:8084/solr/apartment_core/select?q=%s%%3A%s&fl=id&wt=json&indent=true&_=%s' % (searchKey,searchValue,str(time.time())) } } clearKeyUrl = { 'house': { 'test': 'http://192.168.0.216:8080/solr/house_core/update', 'mock': 'http://192.168.0.203:8080/solr/house_core/update', 'trunk': 'http://121.40.105.35:8084/solr/house_core/update' }, 'apartment': { 'test': 'http://192.168.0.216:8080/solr/apartment_core/update', 'mock': 'http://192.168.0.203:8080/solr/apartment_core/update', 'trunk': 'http://121.40.105.35:8084/solr/apartment_core/update' } } deltaImportUrl = { 'house': { 'test': 'http://192.168.0.216:8080/solr/house_core/dataimport?command=delta-import&commit=true&wt=json&indent=true&verbose=false&clean=false&optimize=false&debug=false', 'mock': 'http://192.168.0.216:8080/solr/house_core/dataimport?command=delta-import&commit=true&wt=json&indent=true&verbose=false&clean=false&optimize=false&debug=false', 'trunk': 'http://192.168.0.216:8080/solr/house_core/dataimport?command=delta-import&commit=true&wt=json&indent=true&verbose=false&clean=false&optimize=false&debug=false' }, 'apartment': { 'test': 'http://192.168.0.216:8080/solr/apartment_core/dataimport?command=delta-import&commit=true&wt=json&indent=true&verbose=false&clean=false&optimize=false&debug=false', 'mock': 'http://192.168.0.203:8080/solr/apartment_core/dataimport?command=delta-import&commit=true&wt=json&indent=true&verbose=false&clean=false&optimize=false&debug=false', 'trunk': 'http://121.40.105.35:8084/solr/apartment_core/dataimport?command=delta-import&commit=true&wt=json&indent=true&verbose=false&clean=false&optimize=false&debug=false' } } if searchKey is None and searchValue is None: requests.get(deltaImportUrl[core][condition]) text = requests.get(getKeyUrl[core][condition]).text if text.find('id') == -1: consoleLog('%s-core的solr数据已不存在,无需清理' % core) else: for key in re.findall('\"id\":\"(.*?)\"',text): key.encode('utf-8') payload = "\"1000\" overwrite=\"true\"> " % key querystring = {"wt": "json"} headers = {"Content-Type":"text/xml"} result = requests.post(clearKeyUrl[core][condition],data=payload,headers=headers,params=querystring).text if result.find('0') == -1: consoleLog('%s-core的solr清理异常\n%s' % (core,result),level='ERROR') else: consoleLog('%s-core的solr数据已清理' % core) @errorLog def type_date(self, loc, dateValue): """ 定义type_date方法,用于处理日期控件的传参 :param loc: 接收jquery的选择器的值,如 #id .class css选择器,不是page页面中定义的元素元组 :param dateValue: 具体时间值,格式如2017-01-02 """ #js = "$(\"%s\").removeAttr('readonly');$(\"%s\").attr('value','%s')" % (loc,loc,date) #上面的是调用js原生方法,由于前段框架的问题,原生方法传参无效,需利用jquery调用easyui中的方法 js = "$('%s').datebox('setValue','%s')" % (loc ,dateValue) self.script(js) time.sleep(0.2) @errorLog def type_select(self, loc, selectedValue): """ 定义type_select方法,用于处理下拉控件的传参 :param loc: 接收jquery的选择器的值,如 #id .class css选择器,不是page页面中定义的元素元组 :param selectedValue: 由于页面在单击选择后,会传给后台key,而不是value,所以此处的传参为数据字典中的Key,而非value!!! """ js = "$('%s').combobox('setValue','%s')" % (loc, selectedValue) self.script(js) time.sleep(0.2) @errorLog def type_combotree(self, loc, selectedValue): """ 定义type_combotree方法,用于处理系统中下拉为tree的控件,如部门的选择 :param loc: 接收jquery的选择器的值,如 #id .class css选择器,不是page页面中定义的元素元组 :param selectedValue: 由于页面在单击选择后,会传给后台key,而不是value,所以此处的传参为数据字典中的Key,而非value!!! """ js = r"$('%s').combotree('setValue','%s')" % (loc, selectedValue) self.script(js) time.sleep(0.2) @errorLog def type_checkbox(self, loc, ischecked): """ 定义type_checkbox方法,用于处理复选框控件的传参 :param loc: 接收jquery的选择器的值,如 #id .class css选择器,不是page页面中定义的元素元组 :param ischecked: 为boolean值 """ js = r"$('%s').attr('checked','%s')" % (loc, ischecked) self.script(js) time.sleep(0.2) @errorLog def type_click(self, loc): js = "$('%s').click()" % (loc) self.script(js)%s
#Page.py
###各web页面的实际地址,攻其他pageClass中的操作方法调用
# -*- coding:utf8 -*- #系统管理 userPage = 'http://isz.ishangzu.com/isz_base/jsp/user/userManage.jsp' #用户管理 resPage = 'http://isz.ishangzu.com/isz_base/jsp/user/resManage.jsp' #资源管理 rolePage = 'http://isz.ishangzu.com/isz_base/jsp/user/roleManage.jsp' #角色管理 depPage = 'http://isz.ishangzu.com/isz_base/jsp/user/departManage.jsp' #部门管理 accreditPage = 'http://isz.ishangzu.com/isz_base/jsp/user/loginAuth.jsp' #授权管理 positonPage = 'http://isz.ishangzu.com/isz_base/jsp/user/positionList.jsp' #岗位管理 #客户管理 customerListPage = 'http://isz.ishangzu.com/isz_customer/jsp/customer/customerList.jsp' #租前客户 customerFollowPage = 'http://isz.ishangzu.com/isz_customer/jsp/customer/customerFollowList.jsp' #租客跟进 customerViewPage = 'http://isz.ishangzu.com/isz_customer/jsp/customer/customerViewList.jsp' #租客带看 #楼盘管理 areaPage = 'http://isz.ishangzu.com/isz_house/jsp/districtbusinesscircle/districtBusinessCircle.jsp' #区域商圈 residentiaPage = 'http://isz.ishangzu.com/isz_house/jsp/residential/residentialList.jsp' #楼盘字典 auditResidentiaPage = 'http://isz.ishangzu.com/isz_house/jsp/residential/auditResidentialList.jsp' #楼盘维护 bussinessCirclePage = 'http://isz.ishangzu.com/isz_base/jsp/depbusinesscircle/depBussinessCircleList.jsp' #门店商圈 transferPage = 'http://isz.ishangzu.com/isz_house/jsp/house/transfer/transferList.jsp' #转移房源 storePage = 'http://isz.ishangzu.com/isz_house/jsp/store/storeList.jsp' #门店管理 storeMapPage = 'http://isz.ishangzu.com/isz_house/jsp/store/storeMap.jsp' #门店楼盘 #房源管理 houseAddPage = 'http://isz.ishangzu.com/isz_house/jsp/house/develop/houseDevelopinfoAdd.jsp' #新增房源 houseAuditPage = 'http://isz.ishangzu.com/isz_house/jsp/house/audit/houseAuditIndex.jsp' #审核房源 devHousePage = 'http://isz.ishangzu.com/isz_house/jsp/house/devhouse/houseIndex.jsp' #开发自营房源 resHousePage = 'http://isz.ishangzu.com/isz_house/jsp/house/rent/houseIndex.jsp?from=manageHouseResource' #资料房源 validHousePage = 'http://isz.ishangzu.com/isz_house/jsp/house/invalid/houseIndex.jsp' #失效房源 truHousePage = 'http://isz.ishangzu.com/isz_house/jsp/house/trusteeship/houseIndex.jsp' #托管中的房源 apartmentPage = 'http://isz.ishangzu.com/isz_house/jsp/apartment/apartmentIndex.jsp' #自营房源 customerAptPage = 'http://isz.ishangzu.com/isz_house/jsp/apartment/apartmentList.jsp?for_customer=1' #为客配房 #设计工程 designSharePage = 'http://isz.ishangzu.com/isz_house/jsp/design/designShareList.jsp' # 品牌合租 designEntirePage = 'http://isz.ishangzu.com/isz_house/jsp/design/designEntireList.jsp' # 品牌整租 designManageSharePage = 'http://isz.ishangzu.com/isz_house/jsp/design/designManageShareList.jsp' #托管合租 #合同管理 generalConractPage = 'http://isz.ishangzu.com/isz_contract/jsp/generalcontract/generallist.jsp' #普单合同 entrustContractPage = 'http://isz.ishangzu.com/isz_contract/jsp/entrustcontract/contractList.jsp' #委托合同 apartmentContractPage = 'http://isz.ishangzu.com/isz_contract/jsp/contract/apartmentContract.jsp' #出租合同 apartmentAchievementPage = 'http://isz.ishangzu.com/isz_achievement/jsp/achievement/apartmentAchievementList.jsp' #正常出房 backAchievementPage = 'http://isz.ishangzu.com/isz_achievement//jsp/achievement/back/contractAchievementBackList.jsp' #结算扣回 vacancyAchievementPage = 'http://isz.ishangzu.com/isz_achievement/jsp/achievement/vacancy/apartmentVacancyAchievementList.jsp' #空置亏损 defaultAchievementPage = 'http://isz.ishangzu.com/isz_achievement/jsp/achievement/default/apartmentDefaultAchievementList.jsp' #违约业绩 vacancyDatePage = 'http://isz.ishangzu.com/isz_achievement/jsp/achievement/vacancyList.jsp' #空置日期变更表 contractEndPage = 'http://isz.ishangzu.com/isz_contract/jsp/end/end.jsp' #终止结算 achievementPage = 'http://isz.ishangzu.com/isz_contract/jsp/contractachievement/achievementIndex.jsp' #业绩分成 achievementDepPage = 'http://isz.ishangzu.com/isz_contract/jsp/contractachievement/achievementDepList.jsp' #部门业绩排行榜 achievementUserPage = 'http://isz.ishangzu.com/isz_contract/jsp/contractachievement/achievementUserList.jsp' #个人业绩排行榜 #财务管理 houseContractPayPage = 'http://isz.ishangzu.com/isz_finance/jsp/house/housepay.jsp?tab=1&entrust_type=' #委托合同应付 apartmentContractPayPage = 'http://isz.ishangzu.com/isz_finance/jsp/contractReceivable/apartmentContractReceivableList.jsp' #出租合同应收 reimbursementExpenseListPage = 'http://isz.ishangzu.com/isz_finance/jsp/expense/reimbursementExpenseList.jsp' #报销费用 reimbursementExpenseItemListPage = 'http://isz.ishangzu.com/isz_finance/jsp/expense/reimbursementExpenseItemList.jsp' #报销单详情汇总 houseContractEndPayPage = 'http://isz.ishangzu.com/isz_finance/jsp/houseContractEnd/houseContractEndFlowShouldList.jsp?tab=8&type=' #委托合同终止结算收付 apartmentContractEndPayPage = 'http://isz.ishangzu.com/isz_finance/jsp/apartmentContractEnd/apartmentContractEndFlowShouldList.jsp?tab=3&type=&entrust_type=' #出租合同终止结算收付 depositToReceiptPage= 'http://isz.ishangzu.com/isz_finance/jsp/earnest/turnToReceiptList.jsp' #定金转入合同实收 depositToBreachPage= 'http://isz.ishangzu.com/isz_finance/jsp/earnest/turnToBreachList.jsp' #定金转入违约金
#SQL.py
###对数据库的操作,目前只做对测试数据的清理
# -*- coding:utf8 -*- #数据清理的基类,测试结束后调用此函数 import pymysql from base.Base import consoleLog from base.Base import errorLog from base.Base import Base """ 按照业务逻辑顺序以及主外键约束,清理数据需按照以下顺序执行,否则会造成主表数据删除,其他关联表数据删不掉或者部分表删除报错。前面为模块名称,后面为产生数据的表名 step1:user(sys_user_role、sys_user) step2:residential(residential_buiding_no、residential_buiding_floor、residential_buiding_unit、residential_buiding、residential) setp3:house(house_audit_status_change、house_configuration、house_develop_relation、follow_house、house_rent、house、house_develop_configuration、house_develop) step4:house_contract(house_contract_payable、house_contract_rental_detail、house_contract_rent_detail,house_contract_rent_info,house_contract_sign,house_contract_res,house_contract_landlord,house_contract_attachment,house_contract) step5:fitment(house_room_configuration、house_room_feature、house_room_func、house_room_tag、house_room、apartment、fitment_room、fitment_house) setp6:apartment_contract() """ if Base.test == Base.testCondition[0]: conn = pymysql.connect(host=' ',user=' ',password='',db='',charset='utf8') cursor = conn.cursor() if Base.test == Base.testCondition[1]: conn = pymysql.connect(host='',user='',password='',db=' ',charset='utf8') cursor = conn.cursor() if Base.test == Base.testCondition[2]: conn = pymysql.connect(host='',user='',password='',db='',charset='utf8') cursor = conn.cursor() sql = { #系统用户 'user_01' : ( "delete from sys_user_role where user_id in (select user_id from sys_user where user_name = 'AutoTest')", "delete from sys_user where user_name = 'AutoTest'" ), #楼盘字典栋座 'residential_02' : ( "DELETE from residential where residential_name = 'AutoTest'", "DELETE from residential_building where building_name = 'AutoTest'", "DELETE from residential_building_unit where unit_name = 'AutoTest'", "DELETE from residential_building_floor where floor_name = 'AutoTest'", "DELETE from residential_building_house_no where house_no = 'AutoTest'" ), #新增房源,审核房源,开发自营房源的数据 'house_03' : ( "DELETE from house_audit_status_change where house_id in (SELECT house_id from house where residential_id in (SELECT residential_id from residential where residential_name = 'AutoTest'))", "DELETE from house_configuration where house_id in (SELECT house_id from house where residential_id in (SELECT residential_id from residential where residential_name = 'AutoTest'))", "DELETE from house_develop_relation where house_id in (SELECT house_id from house where residential_id in (SELECT residential_id from residential where residential_name = 'AutoTest'))", "DELETE from follow_house where object_id in (SELECT house_id from house where residential_id in (SELECT residential_id from residential where residential_name = 'AutoTest'))", "DELETE from house_rent where residential_id in (SELECT residential_id from residential where residential_name = 'AutoTest')", "DELETE from house where residential_id in (SELECT residential_id from residential where residential_name = 'AutoTest')", "DELETE from house_develop_configuration where house_develop_id in (SELECT house_develop_id from house_develop where residential_name = 'AutoTest')", "DELETE from house_develop where residential_name = 'AutoTest(auto)'" ), #委托合同 'house_contract_04' : ( "DELETE from house_contract_payable where contract_id in (SELECT contract_id from house_contract where contract_num = 'AutoTest')", "DELETE from house_contract_rental_detail where contract_id in(SELECT contract_id from house_contract where contract_num = 'AutoTest')", "DELETE from house_contract_rent_detail where rent_info_id in (SELECT rent_info_id from house_contract_rent_info where contract_id in (SELECT contract_id from house_contract where contract_num = 'AutoTest'))", "DELETE from house_contract_rent_info where contract_id in (SELECT contract_id from house_contract where contract_num = 'AutoTest')", "DELETE from house_contract_sign where contract_id in (SELECT contract_id from house_contract where contract_num = 'AutoTest')", "DELETE from house_contract_res where contract_id in (SELECT contract_id from house_contract where contract_num = 'AutoTest')", "DELETE from house_contract_landlord where contract_id in (SELECT contract_id from house_contract where contract_num = 'AutoTest')", "DELETE from house_contract_attachment where contract_id in (SELECT contract_id from house_contract where contract_num = 'AutoTest')", "DELETE from workflow_process where object_id in (SELECT contract_id from house_contract where contract_num = 'AutoTest')", "DELETE from house_contract_loss_achievement_detail where loss_achieve_id in (select loss_achieve_id from house_contract_loss_achievement where house_contract_num = 'AutoTest')", "DELETE from house_contract_loss_achievement where house_contract_num = 'AutoTest'", "DELETE from house_contract where contract_num = 'AutoTest'", "DELETE from query_house_contract where contract_num = 'AutoTest'" ), #设计工程 'fitment_05' : ( "DELETE from house_room_configuration where room_id in (SELECT room_id from house_room where house_id in (SELECT house_id from house_contract where contract_num = 'AutoTest'))", "DELETE from house_room_feature where room_id in (SELECT room_id from house_room where house_id in (SELECT house_id from house_contract where contract_num = 'AutoTest'))", "DELETE from house_room_func where room_id in (SELECT room_id from house_room where house_id in (SELECT house_id from house_contract where contract_num = 'AutoTest'))", "DELETE from house_room_tag where room_id in (SELECT room_id from house_room where house_id in (SELECT house_id from house_contract where contract_num = 'AutoTest'))", "DELETE from house_room where house_id in (SELECT house_id from house_contract where contract_num = 'AutoTest')", "DELETE from apartment where house_id in (SELECT house_id from house_contract where contract_num = 'AutoTest')", "DELETE from fitment_room where fitment_id in (SELECT fitment_id from fitment_house where contract_id in (SELECT contract_id from house_contract where contract_num = 'AutoTest'))", "DELETE from fitment_house where contract_id in (SELECT contract_id from house_contract where contract_num = 'AutoTest')" ), #租前客户 'customer_person_06':( "DELETE from follow_customer where object_id in (SELECT customer_id from customer where customer_name = 'AutoTest')", "DELETE from customer_view where customer_id in (SELECT customer_id from customer where customer_name = 'AutoTest')", "DELETE from customer_tel where customer_id in (SELECT customer_id from customer where customer_name = 'AutoTest')", "DELETE from customer_distribution_record where customer_id in (SELECT customer_id from customer where customer_name = 'AutoTest')", "DELETE from customer_business_circle where customer_id in (SELECT customer_id from customer where customer_name = 'AutoTest')", "DELETE from customer where customer_name = 'AutoTest'" ), #出租合同、成交客户,业绩 'apartment_contract_07':( "DELETE from customer_person where person_id in (SELECT person_id from customer_person_relation where customer_id in (SELECT customer_id from customer where customer_name = 'AutoTest'))", "DELETE from customer_person_relation where customer_id in (SELECT customer_id from customer where customer_name = 'AutoTest')", "DELETE from apartment_contract_achievement_detail where achievement_id in (SELECT achievement_id from apartment_contract_achievement where contract_num = 'AutoTest')", "DELETE from apartment_contract_achievement where contract_num = 'AutoTest'", "DELETE from apartment_contract_attachment where contract_id in (SELECT contract_id from apartment_contract where contract_num = 'AutoTest')", "DELETE from apartment_contract_check_in where contract_id in (SELECT contract_id from apartment_contract where contract_num = 'AutoTest')", "DELETE from apartment_contract_relation where contract_id in (SELECT contract_id from apartment_contract where contract_num = 'AutoTest')", "DELETE from apartment_contract_receivable where contract_id in (SELECT contract_id from apartment_contract where contract_num = 'AutoTest')", "DELETE from apartment_contract_rent_info where contract_id in (SELECT contract_id from apartment_contract where contract_num = 'AutoTest')", "DELETE FROM apartment_contract_rent_detail WHERE rent_info_id IN ( SELECT rent_info_id FROM apartment_contract_rent_info WHERE contract_id IN ( SELECT contract_id FROM apartment_contract WHERE contract_num = 'AutoTest' ))", "DELETE from apartment_contract_rental_detail where contract_id in (SELECT contract_id from apartment_contract where contract_num = 'AutoTest')", "DELETE from contract_achievement_detail where achieve_id in (select achieve_id from contract_achievement where contract_id in (SELECT contract_id from apartment_contract where contract_num = 'AutoTest'))", "DELETE from contract_achievement where contract_id in (SELECT contract_id from apartment_contract where contract_num = 'AutoTest')", "DELETE from apartment_contract where contract_num = 'AutoTest'", "DELETE from query_apartment_contract where contract_num = 'AutoTest'" ), #出租合同终止结算 'apartment_contract_end_08':( "DELETE from back_original_achievement_detail where achieve_id in (SELECT achieve_id from back_achievement where end_id = (SELECT end_id from apartment_contract_end where contract_id = (SELECT contract_id from apartment_contract where contract_num = 'AutoTest')))", "DELETE from back_house_contract_achievement_detail where achieve_id in (SELECT achieve_id from back_achievement where contract_num = 'AutoTest')", "DELETE from back_achievement_detail where achieve_id in (SELECT achieve_id from back_achievement where contract_num = 'AutoTest')", "DELETE from back_achievement where contract_num = 'AutoTest'", "DELETE from breach_original_achievement_detail where achieve_id in (SELECT achieve_id from breach_achievement where contract_num = 'AutoTest')", "DELETE from breach_achievement_detail where achieve_id in (SELECT achieve_id from breach_achievement where contract_num = 'AutoTest')", "DELETE from breach_achievement where contract_num = 'AutoTest'", "DELETE from apartment_contract_end where contract_id IN (SELECT contract_id from apartment_contract where contract_num = 'AutoTest')" ), #委托合同终止结算 'house_contract_end_09':( "DELETE from house_contract_loss_achievement_detail where loss_achieve_id in (SELECT loss_achieve_id from house_contract_loss_achievement where house_contract_num = 'AutoTest')", "DELETE from house_contract_loss_achievement where house_contract_num = 'AutoTest'", "DELETE from house_contract_end where contract_id = (SELECT contract_id from house_contract where contract_num = 'AutoTest')", ) } def execute(sql): cursor.execute(sql) conn.commit() @errorLog def clear_data(success): """清理测试数据""" try: if success == 1: for values in ['user_01']: for value in sql.get(values): consoleLog(value) execute(value) conn.commit() consoleLog('用户模块测试数据清理完毕') elif success == 2: for values in ['residential_02','user_01']: for value in sql.get(values): consoleLog(value) cursor.execute(value) conn.commit() consoleLog('楼盘、用户模块测试数据清理完毕') elif success == 3: for values in ['house_03','residential_02','user_01']: for value in sql.get(values): consoleLog(value) cursor.execute(value) conn.commit() consoleLog('房源、楼盘、用户模块测试数据清理完毕') elif success == 4: for values in ['house_contract_04','house_03','residential_02','user_01']: for value in sql.get(values): consoleLog(value) cursor.execute(value) conn.commit() consoleLog('委托合同、房源、楼盘、用户模块测试数据清理完毕') elif success == 5: for values in ['fitment_05','house_contract_04','house_03','residential_02','user_01']: for value in sql.get(values): consoleLog(value) cursor.execute(value) conn.commit() consoleLog('设计工程、委托合同、房源、楼盘、用户模块测试数据清理完毕') elif success == 6: for values in ['customer_person_06','fitment_05','house_contract_04','house_03','residential_02','user_01']: for value in sql.get(values): consoleLog(value) cursor.execute(value) conn.commit() consoleLog('租前客户、设计工程、委托合同、房源、楼盘、用户模块测试数据清理完毕') elif success == 7: for values in ['apartment_contract_07','customer_person_06','fitment_05','house_contract_04','house_03','residential_02','user_01']: for value in sql.get(values): consoleLog(value) cursor.execute(value) conn.commit() consoleLog('出租合同、租前客户、设计工程、委托合同、房源、楼盘、用户模块测试数据清理完毕') elif success == 8: for values in ['apartment_contract_end_08','apartment_contract_07','customer_person_06','fitment_05','house_contract_04','house_03','residential_02','user_01']: for value in sql.get(values): consoleLog(value) cursor.execute(value) conn.commit() consoleLog('出租合同终止、出租合同、租前客户、设计工程、委托合同、房源、楼盘、用户模块测试数据清理完毕') elif success == 9: for values in ['house_contract_end_09','apartment_contract_end_08','apartment_contract_07','customer_person_06','fitment_05','house_contract_04','house_03','residential_02','user_01']: for value in sql.get(values): consoleLog(value) cursor.execute(value) conn.commit() consoleLog('委托合同终止、出租合同终止、出租合同、租前客户、设计工程、委托合同、房源、楼盘、用户模块测试数据清理完毕') except: consoleLog('清理测试数据出现异常,请手动清理以下模块产生的数据: %s 、 当前执行SQL: %s 、%s') % (values,value,Exception.message) finally: cursor.close() conn.close() @errorLog def serach(sql): cursor.execute(sql) value = cursor.fetchone() conn.commit() return value[0].encode('utf-8') if __name__ == '__main__': clear_data(3)
#test.py
###自动化测试的入口,继承unittest框架,实例化各pageClass并调用其对应的业务操作方法。目前只定义了一个用例,因为当前关心的是流程,不是各case。后期稳定的基础上,加入大量case后,会使用套件去管理各case
# -*- coding:utf8 -*- import time import unittest from selenium import webdriver import SQL from contract.ApartmentContractEndPage import ApartmentContractEndPage from contract.ApartmentContractPage import ApartmentContractPage from contract.HouseContractEndPage import HouseContractEndPage from contract.HouseContractPage import HouseContractPage from customer.CustomerPage import CustomerPage from finance.ReimbuisementPage import ReimbuisementPage from fitment.DesignSharePage import DesignSharePage from house.ApartmentPage import ApartmentPage from house.HouseAddPage import HouseAddPage from house.HouseAuditPage import HouseAuditPage from house.ResidentiaPage import ResidentialPage from user.Login import LoginPage from user.UserPage import UserPage from base.Base import Base class Test(unittest.TestCase,Base): #测试开始后调用的方法:实例化webdriver,并设置全局隐式等待30秒 def setUp(self): self.driver = webdriver.Chrome() self.driver.implicitly_wait(30) #测试结束或者中途报错后调用的方法:退出浏览器并删除测试过程中产生的数据 def tearDown(self): self.driver.get_screenshot_as_file('error.jpg') if self.test == self.testCondition[0]: if Base.succeed > 0: SQL.clear_data(Base.succeed) else: pass self.solr('house', self.test, searchKey='residential_name', searchValue='AutoTest') self.solr('apartment',self.test,searchKey='residential_name', searchValue='AutoTest') self.driver.quit() #测试主流程 def test_test(self): #登录系统 loginPage = LoginPage(self.driver) #loginPage.login('18279881085','a123456789') loginPage.login('15168368432','isz1234567') #新增用户并重新登录 userPage = UserPage(self.driver) position = "SELECT * from sys_position where position_name = '测试工程师(后台)'" userPage.addUser(username='AutoTest',userphone='13666666665',userpost=SQL.serach(position),userrole='00000000000000000000000000000000',usermail='[email protected]') loginPage.anewLogin('13666666665','isz12345') #新增楼盘,新增栋座 residentialPage = ResidentialPage(self.driver) residentialPage.addResidential() #新增房源 houseAddPage = HouseAddPage(self.driver) houseAddPage.addhousepage() #审核房源 houseAuditPage = HouseAuditPage(self.driver) houseAuditPage.audit() #新增委托合同 houseContractPage = HouseContractPage(self.driver) houseContractPage.addHouseContract() #设计装修合租房源 designSharePage = DesignSharePage(self.driver) designSharePage.designhouse() #委托合同审核,需要等待apartment-solr出现,所以放在设计工程之后 houseContractPage.auditHouseContract() #自营房源合租定价 apartmentPage = ApartmentPage(self.driver) apartmentPage.addhouserent() #创建租前客户 customerPage = CustomerPage(self.driver) customerPage.addCustomer() #新增及审核出租合同 apartmentContractPage = ApartmentContractPage(self.driver) apartmentContractPage.addApartmentContract() apartmentContractPage.auditApartmentContract() #新增及审核出租合同终止结算 apartmentContractEndPage = ApartmentContractEndPage(self.driver) apartmentContractEndPage.addContractEnd() apartmentContractEndPage.auditContractEnd() #新增及审核报销单 apartmentPage.addReimbursement() reimbuisementPage = ReimbuisementPage(self.driver) reimbuisementPage.auditReimbuisement() # 新增及审核委托合同终止结算 houseContractEndPage = HouseContractEndPage(self.driver) houseContractEndPage.addContractEnd() houseContractEndPage.auditContractEnd() #页面删除 apartmentContractEndPage.delContractEnd() #出租合同终止删除 apartmentContractPage.delContract() #出租合同删除 customerPage.delCustomer() #租前客户删除 houseContractEndPage.delContractEnd() #委托合同终止删除 houseContractPage.delContract() #委托合同删除 if __name__ == '__main__': unittest.main()