实习项目总结
项目名称:基于selenium的交警展示平台的ui自动化测试框架搭建
项目描述:
web的ui自动化项目的框架搭建。数据库中数据依照一定规则被推送到审核平台进行审核,审核后的数据规则扭转到另一部分web后端,根据一定的去重规则进行展示。
项目架构
测试点:
1.比对高速展示平台中的数据是否按照规则显示在展示平台中。
2.比对点击任何一个事件后所出现浮窗中的事件与高速事件框中的时间是否一致。
common文件
bus文件:
data_process
import math import time EARTH_REDIUS = 6378.137 class Date_Process: # 计算经纬度 @staticmethod def getDistance(lat1, lng1, lat2, lng2): def rad(self, d): return d * math.pi / 180.0 radLat1 = rad(lat1) radLat2 = rad(lat2) a = radLat1 - radLat2 b = rad(lng1) - rad(lng2) s = 2 * math.asin(math.sqrt(math.pow(math.sin(a/2), 2) + math.cos(radLat1) * math.cos(radLat2) * math.pow(math.sin(b/2), 2))) s = s * EARTH_REDIUS return s*100 @staticmethod def strftime(timestamp): timearry = time.localtime(timestamp) datetime = time.strftime('%Y-%m-%d %H:%M:%S',timearry) return datetime # def Time_gap(self,timestamp1,timestamp2):
login
# coding=utf-8 import time from selenium import webdriver # driver = webdriver.Chrome() #打开浏览器 from common.pub import readconfig from selenium.common.exceptions import NoSuchElementException,TimeoutException from selenium.webdriver import ActionChains from common.pub.selenium_rewrite import isElementExist from common.pub.readconfig import ReadConfig Prodir = readconfig.proDir class Login(): def __init__(self,driver): localreadconfig = ReadConfig() self.name = localreadconfig.get_login('username') self.passwd = localreadconfig.get_login('password') self.url = localreadconfig.get_login('url') self.driver=driver def login_chrome(self): driver=self.driver driver.implicitly_wait(10) driver.maximize_window() driver.get(self.url) #进入url user_name = driver.find_element_by_name('username') password = driver.find_element_by_name('password') login_but = driver.find_element_by_tag_name('button') time.sleep(1) user_name.send_keys(self.name) #输入账号 password.send_keys(self.passwd) #密码 try: move_block = driver.find_element_by_class_name('verify-move-block') # 验证码为滑动模块 print("验证为滑动模块") while True: action = ActionChains(driver) action.click_and_hold(move_block) action.move_by_offset(300, 0) action.release() action.perform() login_but.click() time.sleep(2) flag = isElementExist(driver.find_element_by_class_name, 'location') if flag: break except NoSuchElementException as e: code = driver.find_element_by_name('code') # 验证码 print("验证为验证码输入") code.send_keys("_unlock") # 输入万能验证码_unlock login_but.click() for i in range(10): #最多等待20s time.sleep(2) flag = isElementExist(driver.find_element_by_class_name, 'location') if flag: break if i==9: print("等待20s还未正常进入主界面")
screen_shot
# coding=utf-8 import time from selenium import webdriver # driver = webdriver.Chrome() #打开浏览器 from common.pub import readconfig from selenium.common.exceptions import NoSuchElementException,TimeoutException from selenium.webdriver import ActionChains from common.pub.selenium_rewrite import isElementExist from common.pub.readconfig import ReadConfig Prodir = readconfig.proDir class Login(): def __init__(self,driver): localreadconfig = ReadConfig() self.name = localreadconfig.get_login('username') self.passwd = localreadconfig.get_login('password') self.url = localreadconfig.get_login('url') self.driver=driver def login_chrome(self): driver=self.driver driver.implicitly_wait(10) driver.maximize_window() driver.get(self.url) #进入url user_name = driver.find_element_by_name('username') password = driver.find_element_by_name('password') login_but = driver.find_element_by_tag_name('button') time.sleep(1) user_name.send_keys(self.name) #输入账号 password.send_keys(self.passwd) #密码 try: move_block = driver.find_element_by_class_name('verify-move-block') # 验证码为滑动模块 print("验证为滑动模块") while True: action = ActionChains(driver) action.click_and_hold(move_block) action.move_by_offset(300, 0) action.release() action.perform() login_but.click() time.sleep(2) flag = isElementExist(driver.find_element_by_class_name, 'location') if flag: break except NoSuchElementException as e: code = driver.find_element_by_name('code') # 验证码 print("验证为验证码输入") code.send_keys("_unlock") # 输入万能验证码_unlock login_but.click() for i in range(10): #最多等待20s time.sleep(2) flag = isElementExist(driver.find_element_by_class_name, 'location') if flag: break if i==9: print("等待20s还未正常进入主界面")
selectconfig
# coding=utf-8 import time from selenium.common.exceptions import NoSuchElementException from common.pub.selenium_rewrite import is_visible class LocationSelect(): def __init__(self,driver,province,city): self.driver = driver self.city = standardinput(city) self.prov***andardinput(province) self.baseelem = "//*[@id='IIInsomnia_province_wrap']/li[@data-name=%s]" %(self.province) def act(self): self.act_kuang() self.select_province() self.select_city() def act_kuang(self): element = '完成' try: self.driver.find_elements_by_link_text(element)[0].click() except Exception: print('完成框已经消失/n输入框已唤醒') time.sleep(2) select_city = self.driver.find_element_by_class_name('location-c') select_city.click() def select_province(self): try: pro=self.get_province() pro.click() except NoSuchElementException: print("请重新输入省份(规范):/'**省/'") def select_city(self): try: cit=self.get_city() cit.click() time.sleep(2) except NoSuchElementException: print("请重新输入市名(规范):/'**市/'") def get_province(self): prov = self.driver.find_element_by_xpath(self.baseelem) return prov def get_city(self): elem =self.baseelem+"/ul/li[@title=%s]" %(self.city) cit = self.driver.find_element_by_xpath(elem) return cit # #定位到对应城市(采用鼠标点击方式来唤出) class MapDisplay(): def __init__(self,driver): self.driver = driver self.dic = {'道路实景':["//div[@id='layerbox-street']/input","//div[@id='layerbox-street']/div[3]"], '高速':["//div[@id='layerbox-high-road']/input","//div[@id='layerbox-high-road']/div[3]"], '路径规划':["//div[@id='layerbox-route']/input","//div[@id='layerbox-route']/div[3]"], '街面事件':["//div[@id='layerbox-street-event']/input","//div[@id='layerbox-street-event']/div[3]"], '城管事件':["//div[@id='layerbox-urban-event']/input","//div[@id='layerbox-urban-event']/div[3]"], '交管事件': ["//div[@id='layerbox-traffic-event']/input", "//div[@id='layerbox-traffic-event']/div[3]"], '覆盖频次': ["//div[@id='layerbox-override-count']/input", "//div[@id='layerbox-override-count']/div[3]"], '车辆位置':["//div[@id='layerbox-car-locate']/input","//div[@id='layerbox-car-locate']/div[3]"], '道路标牌':["//div[@id='layerbox-road-signs']/input","//div[@id='layerbox-road-signs']/div[3]"], 'POI':["//div[@id='layerbox-road-poi']/input","//div[@id='layerbox-road-poi']/div[3]"], '新建道路':["//div[@id='layerbox-new-roads']/input","//div[@id='layerbox-new-roads']/div[3]"], '路况': ["//div[@id='layerbox-road-condition']/input", "//div[@id='layerbox-road-condition']/div[3]"], '交通事件': ["//div[@id='layerbox-traffic-incident']/input", "//div[@id='layerbox-traffic-incident']/div[3]"], } def select(self,name): xpath = self.dic[name] try: element_judge = self.driver.find_element_by_xpath(xpath[0]) if not element_judge.is_enabled(): raise SelectWarning(name) elif not element_judge.is_selected(): # WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.XPATH, xpath[1]))) if is_visible(self.driver,xpath[1]): self.driver.find_element_by_xpath(xpath[1]).click() # 这里有点奇怪,元素已存在还需要等待 except KeyError: print('选项不存在') def cancel(self,name): try: xpath = self.dic[name] element_judge = self.driver.find_element_by_xpath(xpath[0]) element = self.driver.find_element_by_xpath(xpath[1]) if element_judge.is_selected(): element.click() except KeyError: print('%s选项不存在' %name) class SelectWarning(Exception): def __init__(self, name): self.name = name def __str__(self): print('%s 不可选' %(self.name)) def isElementExist(method, element): flag = True try: method(element) except: flag = False finally: return flag def standardinput(s): if not s.startswith("'"): s="'"+s+"'" return s class High_way_display(MapDisplay): def __init__(self,driver): # super(High_way_display, self).__init__(driver self.driver=driver locator="//div[@class='introjs-tooltipbuttons']/a" if is_visible(self.driver,locator): self.driver.find_element_by_xpath(locator).click() time.sleep(2) self.dic = {'事故':["//div[@class='layui-form']/div[1]/input","//div[@class='layui-form']/div[1]/div[1]"], '团雾':["//div[@class='layui-form']/div[2]/input","//div[@class='layui-form']/div[2]/div[1]"], '行人':["//div[@class='layui-form']/div[3]/input","//div[@class='layui-form']/div[3]/div[1]"], '低速':["//div[@class='layui-form']/div[4]/input","//div[@class='layui-form']/div[4]/div[1]"], '抛洒':["//div[@class='layui-form']/div[5]/input","//div[@class='layui-form']/div[5]/div[1]"], '施工':["//div[@class='layui-form']/div[6]/input","//div[@class='layui-form']/div[6]/div[1]"], '占道违停':["//div[@class='layui-form']/div[7]/input","//div[@class='layui-form']/div[7]/div[1]"], '占道行驶':["//div[@class='layui-form']/div[8]/input","//div[@class='layui-form']/div[8]/div[1]"], '拥堵':["//div[@class='layui-form']/div[9]/input", "//div[@class='layui-form']/div[9]/div[1]/i"], } class Timedate_select: ''' :param num:'代表是第几天' :return: 返回对应天的元素 ''' def __init__(self,driver): self.driver=driver def select_time(self,num): xpath=self.__get_element(num) if is_visible(self.driver, xpath): self.driver.find_element_by_xpath(xpath).click() else: raise ValueError return self.driver.find_element_by_xpath(xpath).text def __get_element(self,num): num=str(num) xpath = "//ul[@id='dates_x']/li[%s]" %num return xpath
pub
browser_engine
# coding=utf-8 import os.path # from configparser import ConfigParser from logging import Logger from common.pub import readconfig from common.pub.Log import MyLog as Log from selenium import webdriver localReadConfig = readconfig.ReadConfig() # logger = Logger(logger='BrowserEngine').getlog() log = Log.get_log() logger = log.get_logger() class BrowserEngine(object): dir = os.path.dirname(os.path.abspath('.')) # 相对路径获取方法 chrome_dir_path = dir + '/drivers/chromedriver.exe' # 如果把chromedriver放到python根目录下,则可省了 ie_driver_path = dir + '/drivers/IEDriverServer.exe' def __init__(self): # 加载启动项 pass # self.option = webdriver.ChromeOptions() # self.option.add_argument('headless') # 从配置文件config.ini读取浏览器等信息 def open_browser(self): # config = ConfigParser() # file_path = os.path.dirname(os.getcwd()) + '/config/config.ini' # file_path = os.path.dirname(os.path.abspath('.')) + '/config/config.ini' # config.read(file_path,encoding='UTF-8') # config.read(file_path,encoding='UTF-8'), 如果代码有中文注释,用这个,不然报解码错误 browser = localReadConfig.get_browserType("browserName") # logger.info("You had select %s browser." % browser) url = localReadConfig.get_login("url") # logger.info("The test server url is: %s" % url) if browser == "Firefox": driver = webdriver.Firefox() # logger.info("Starting firefox browser.") elif browser == "Chrome": # driver = webdriver.Chrome(self.chrome_driver_path) driver = webdriver.Chrome() # driver = webdriver.Chrome(chrome_options=self.option) # 调用option,不打开浏览器运行testcase # driver =webdriver.Chrome() # logger.info("Starting Chrome browser.") elif browser == "IE": driver = webdriver.Ie(self.ie_driver_path) # logger.info("Starting IE browser.") return driver # driver.get(url) # # logger.info("Open url: %s" % url) # driver.maximize_window() # # logger.info("Maximize the current window.") # driver.implicitly_wait(10) # # logger.info("Set implicitly wait 10 seconds.") # 退出浏览器 # def quit_browser(self): # self.driver.quit() # logger.info("Now, Close and quit the browser.")
dbconfig
# coding=utf-8 import MySQLdb import readconfig localreadconfig = readconfig.ReadConfig() # class Show_Error(Exception): # def __init__(self): # pass # # def __str__(self): # print('平台上展示的数据不存在于筛选数据中,打印异常数据') class DbManipulate: def __init__(self): self.ip = localreadconfig.get_db('ip') self.db_username = localreadconfig.get_db('db_username') self.db_password = localreadconfig.get_db('db_password') self.test_db = localreadconfig.get_db('test_db') self.db= MySQLdb.connect(self.ip, self.db_username, self.db_password, self.test_db, charset='utf8') self.cursor = self.db.cursor() # 语句查询 def query(self,query_sentence): self.cursor.execute(query_sentence) result = self.cursor.fetchall() return result # 查询后再获取字段值 def get_fields(self): fields = self.cursor.description return fields
excelconfig
# coding=utf-8 import xlwt # 导出数据到excel def export(fields,results, table_name, outputpath): ''' :param fields:数据库取出的字段值 :param results: 列表元组或者元组元组 :param table_name: :param outputpath: :return: ''' # 搜取所有结果 # 获取MYSQL里面的数据字段名称 workbook = xlwt.Workbook() sheet = workbook.add_sheet('table_' + table_name, cell_overwrite_ok=True) # 写上字段信息 for field in range(0, len(fields)): sheet.write(0, field, fields[field][0]) # 获取并写入数据段信息 row = 1 col = 0 for row in range(1, len(results) + 1): for col in range(0, len(fields)): sheet.write(row, col, u'%s' % results[row - 1][col]) workbook.save(outputpath)
HTMLTestRunner
""" A TestRunner for use with the Python unit testing framework. It generates a HTML report to show the result at a glance. The simplest way to use this is to invoke its main method. E.g. import unittest import HTMLTestRunner ... define your tests ... if __name__ == '__main__': HTMLTestRunner.main() For more customization options, instantiates a HTMLTestRunner object. HTMLTestRunner is a counterpart to unittest's TextTestRunner. E.g. # output to a file fp = file('my_report.html', 'wb') runner = HTMLTestRunner.HTMLTestRunner( stream=fp, title='My unit test', description='This demonstrates the report output by HTMLTestRunner.' ) # Use an external stylesheet. # See the Template_mixin class for more customizable options runner.STYLESHEET_TMPL = '<link rel="stylesheet" href="my_stylesheet.css" type="text/css">' # run the test runner.run(my_test_suite) ------------------------------------------------------------------------ Copyright (c) 2004-2007, Wai Yip Tung All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name Wai Yip Tung nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """ # URL: http://tungwaiyip.info/software/HTMLTestRunner.html __author__ = "Wai Yip Tung" __version__ = "0.8.2" """ Change History Version 0.8.2 * Show output inline instead of popup window (Viorel Lupu). Version in 0.8.1 * Validated XHTML (Wolfgang Borgert). * Added description of test classes and test cases. Version in 0.8.0 * Define Template_mixin class for customization. * Workaround a IE 6 bug that it does not treat <script> block as CDATA. Version in 0.7.1 * Back port to Python 2.3 (Frank Horowitz). * Fix missing scroll bars in detail log (Podi). """ # TODO: color stderr # TODO: simplify javascript using ,ore than 1 class in the class attribute? import datetime import StringIO import sys import time import unittest from xml.sax import saxutils # ------------------------------------------------------------------------ # The redirectors below are used to capture output during testing. Output # sent to sys.stdout and sys.stderr are automatically captured. However # in some cases sys.stdout is already cached before HTMLTestRunner is # invoked (e.g. calling logging.basicConfig). In order to capture those # output, use the redirectors for the cached stream. # # e.g. # >>> logging.basicConfig(stream=HTMLTestRunner.stdout_redirector) # >>> class OutputRedirector(object): """ Wrapper to redirect stdout or stderr """ def __init__(self, fp): self.fp = fp def write(self, s): self.fp.write(s) def writelines(self, lines): self.fp.writelines(lines) def flush(self): self.fp.flush() stdout_redirector = OutputRedirector(sys.stdout) stderr_redirector = OutputRedirector(sys.stderr) # ---------------------------------------------------------------------- # Template class Template_mixin(object): """ Define a HTML template for report customerization and generation. Overall structure of an HTML report HTML +------------------------+ |<html> | | <head> | | | | STYLESHEET | | +----------------+ | | | | | | +----------------+ | | | | </head> | | | | <body> | | | | HEADING | | +----------------+ | | | | | | +----------------+ | | | | REPORT | | +----------------+ | | | | | | +----------------+ | | | | ENDING | | +----------------+ | | | | | | +----------------+ | | | | </body> | |</html> | +------------------------+ """ STATUS = { 0: 'pass', 1: 'fail', 2: 'error', } DEFAULT_TITLE = 'Unit Test Report' DEFAULT_DESCRIPTION = '' # ------------------------------------------------------------------------ # HTML Template HTML_TMPL = r"""<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>%(title)s</title> <meta name="generator" content="%(generator)s"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> %(stylesheet)s </head> <body> <script language="javascript" type="text/javascript"><!-- output_list = Array(); /* level - 0:Summary; 1:Failed; 2:All */ function showCase(level) { trs = document.getElementsByTagName("tr"); for (var i = 0; i < trs.length; i++) { tr = trs[i]; id = tr.id; if (id.substr(0,2) == 'ft') { if (level < 1) { tr.className = 'hiddenRow'; } else { tr.className = ''; } } if (id.substr(0,2) == 'pt') { if (level > 1) { tr.className = ''; } else { tr.className = 'hiddenRow'; } } } } function showClassDetail(cid, count) { var id_list = Array(count); var toHide = 1; for (var i = 0; i < count; i++) { tid0 = 't' + cid.substr(1) + '.' + (i+1); tid = 'f' + tid0; tr = document.getElementById(tid); if (!tr) { tid = 'p' + tid0; tr = document.getElementById(tid); } id_list[i] = tid; if (tr.className) { toHide = 0; } } for (var i = 0; i < count; i++) { tid = id_list[i]; if (toHide) { document.getElementById('div_'+tid).style.display = 'none' document.getElementById(tid).className = 'hiddenRow'; } else { document.getElementById(tid).className = ''; } } } function showTestDetail(div_id){ var details_div = document.getElementById(div_id) var displayState = details_div.style.display // alert(displayState) if (displayState != 'block' ) { displayState = 'block' details_div.style.display = 'block' } else { details_div.style.display = 'none' } } function html_escape(s) { s = s.replace(/&/g,'&'); s = s.replace(/</g,'<'); s = s.replace(/>/g,'>'); return s; } /* obsoleted by detail in <div> function showOutput(id, name) { var w = window.open("", //url name, "resizable,scrollbars,status,width=800,height=450"); d = w.document; d.write("<pre>"); d.write(html_escape(output_list[id])); d.write("\n"); d.write("<a href='javascript:window.close()'>close</a>\n"); d.write("</pre>\n"); d.close(); } */ --></script> %(heading)s %(report)s %(ending)s </body> </html> """ # variables: (title, generator, stylesheet, heading, report, ending) # ------------------------------------------------------------------------ # Stylesheet # # alternatively use a <link> for external style sheet, e.g. # <link rel="stylesheet" href="$url" type="text/css"> STYLESHEET_TMPL = """ <style type="text/css" media="screen"> body { font-family: verdana, arial, helvetica, sans-serif; font-size: 80%; } table { font-size: 100%; } pre { } /* -- heading ---------------------------------------------------------------------- */ h1 { font-size: 16pt; color: gray; } .heading { margin-top: 0ex; margin-bottom: 1ex; } .heading .attribute { margin-top: 1ex; margin-bottom: 0; } .heading .description { margin-top: 4ex; margin-bottom: 6ex; } /* -- css div popup ------------------------------------------------------------------------ */ a.popup_link { } a.popup_link:hover { color: red; } .popup_window { display: none; position: relative; left: 0px; top: 0px; /*border: solid #627173 1px; */ padding: 10px; background-color: #E6E6D6; font-family: "Lucida Console", "Courier New", Courier, monospace; text-align: left; font-size: 8pt; width: 500px; } } /* -- report ------------------------------------------------------------------------ */ #show_detail_line { margin-top: 3ex; margin-bottom: 1ex; } #result_table { width: 80%; border-collapse: collapse; border: 1px solid #777; } #header_row { font-weight: bold; color: white; background-color: #777; } #result_table td { border: 1px solid #777; padding: 2px; } #total_row { font-weight: bold; } .passClass { background-color: #6c6; } .failClass { background-color: #c60; } .errorClass { background-color: #c00; } .passCase { color: #6c6; } .failCase { color: #c60; font-weight: bold; } .errorCase { color: #c00; font-weight: bold; } .hiddenRow { display: none; } .testcase { margin-left: 2em; } /* -- ending ---------------------------------------------------------------------- */ #ending { } </style> """ # ------------------------------------------------------------------------ # Heading # HEADING_TMPL = """<div class='heading'> <h1>%(title)s</h1> %(parameters)s <p class='description'>%(description)s</p> </div> """ # variables: (title, parameters, description) HEADING_ATTRIBUTE_TMPL = """<p class='attribute'><strong>%(name)s:</strong> %(value)s</p> """ # variables: (name, value) # ------------------------------------------------------------------------ # Report # REPORT_TMPL = """ <p id='show_detail_line'>Show <a href='javascript:showCase(0)'>Summary</a> <a href='javascript:showCase(1)'>Failed</a> <a href='javascript:showCase(2)'>All</a> </p> <table id='result_table'> <colgroup> <col align='left' /> <col align='right' /> <col align='right' /> <col align='right' /> <col align='right' /> <col align='right' /> </colgroup> <tr id='header_row'> <td>Test Group/Test case</td> <td>Count</td> <td>Pass</td> <td>Fail</td> <td>Error</td> <td>View</td> </tr> %(test_list)s <tr id='total_row'> <td>Total</td> <td>%(count)s</td> <td>%(Pass)s</td> <td>%(fail)s</td> <td>%(error)s</td> <td> </td> </tr> </table> """ # variables: (test_list, count, Pass, fail, error) REPORT_CLASS_TMPL = r""" <tr class='%(style)s'> <td>%(desc)s</td> <td>%(count)s</td> <td>%(Pass)s</td> <td>%(fail)s</td> <td>%(error)s</td> <td><a href="javascript:showClassDetail('%(cid)s',%(count)s)">Detail</a></td> </tr> """ # variables: (style, desc, count, Pass, fail, error, cid) REPORT_TEST_WITH_OUTPUT_TMPL = r""" <tr id='%(tid)s' class='%(Class)s'> <td class='%(style)s'><div class='testcase'>%(desc)s</div></td> <td colspan='5' align='center'> <!--css div popup start--> <a class="popup_link" onfocus='this.blur();' href="javascript:showTestDetail('div_%(tid)s')" > %(status)s</a> <div id='div_%(tid)s' class="popup_window"> <div style='text-align: right; color:red;cursor:pointer'> <a onfocus='this.blur();' onclick="document.getElementById('div_%(tid)s').style.display = 'none' " > [x]</a> </div> <pre> %(script)s </pre> </div> <!--css div popup end--> </td> </tr> """ # variables: (tid, Class, style, desc, status) REPORT_TEST_NO_OUTPUT_TMPL = r""" <tr id='%(tid)s' class='%(Class)s'> <td class='%(style)s'><div class='testcase'>%(desc)s</div></td> <td colspan='5' align='center'>%(status)s</td> </tr> """ # variables: (tid, Class, style, desc, status) REPORT_TEST_OUTPUT_TMPL = r""" %(id)s: %(output)s """ # variables: (id, output) # ------------------------------------------------------------------------ # ENDING # ENDING_TMPL = """<div id='ending'> </div>""" # -------------------- The end of the Template class ------------------- TestResult = unittest.TestResult class _TestResult(TestResult): # note: _TestResult is a pure representation of results. # It lacks the output and reporting ability compares to unittest._TextTestResult. def __init__(self, verbosity=1): TestResult.__init__(self) self.stdout0 = None self.stderr0 = None self.success_count = 0 self.failure_count = 0 self.error_count = 0 self.verbosity = verbosity # result is a list of result in 4 tuple # ( # result code (0: success; 1: fail; 2: error), # TestCase object, # Test output (byte string), # stack trace, # ) self.result = [] def startTest(self, test): TestResult.startTest(self, test) # just one buffer for both stdout and stderr self.outputBuffer = StringIO.StringIO() stdout_redirector.fp = self.outputBuffer stderr_redirector.fp = self.outputBuffer self.stdout0 = sys.stdout self.stderr0 = sys.stderr sys.stdout = stdout_redirector sys.stderr = stderr_redirector def complete_output(self): """ Disconnect output redirection and return buffer. Safe to call multiple times. """ if self.stdout0: sys.stdout = self.stdout0 sys.stderr = self.stderr0 self.stdout0 = None self.stderr0 = None return self.outputBuffer.getvalue() def stopTest(self, test): # Usually one of addSuccess, addError or addFailure would have been called. # But there are some path in unittest that would bypass this. # We must disconnect stdout in stopTest(), which is guaranteed to be called. self.complete_output() def addSuccess(self, test): self.success_count += 1 TestResult.addSuccess(self, test) output = self.complete_output() self.result.append((0, test, output, '')) if self.verbosity > 1: sys.stderr.write('ok ') sys.stderr.write(str(test)) sys.stderr.write('\n') else: sys.stderr.write('.') def addError(self, test, err): self.error_count += 1 TestResult.addError(self, test, err) _, _exc_str = self.errors[-1] output = self.complete_output() self.result.append((2, test, output, _exc_str)) if self.verbosity > 1: sys.stderr.write('E ') sys.stderr.write(str(test)) sys.stderr.write('\n') else: sys.stderr.write('E') def addFailure(self, test, err): self.failure_count += 1 TestResult.addFailure(self, test, err) _, _exc_str = self.failures[-1] output = self.complete_output() self.result.append((1, test, output, _exc_str)) if self.verbosity > 1: sys.stderr.write('F ') sys.stderr.write(str(test)) sys.stderr.write('\n') else: sys.stderr.write('F') class HTMLTestRunner(Template_mixin): """ """ def __init__(self, stream=sys.stdout, verbosity=1, title=None, description=None): self.stream = stream self.verbosity = verbosity if title is None: self.title = self.DEFAULT_TITLE else: self.title = title if description is None: self.description = self.DEFAULT_DESCRIPTION else: self.description = description self.startTime = datetime.datetime.now() def run(self, test): "Run the given test case or test suite." result = _TestResult(self.verbosity) test(result) self.stopTime = datetime.datetime.now() self.generateReport(test, result) print >>sys.stderr, '\nTime Elapsed: %s' % (self.stopTime-self.startTime) return result def sortResult(self, result_list): # unittest does not seems to run in any particular order. # Here at least we want to group them together by class. rmap = {} classes = [] for n,t,o,e in result_list: cls = t.__class__ if not rmap.has_key(cls): rmap[cls] = [] classes.append(cls) rmap[cls].append((n,t,o,e)) r = [(cls, rmap[cls]) for cls in classes] return r def getReportAttributes(self, result): """ Return report attributes as a list of (name, value). Override this to add custom attributes. """ startTime = str(self.startTime)[:19] duration = str(self.stopTime - self.startTime) status = [] if result.success_count: status.append('Pass %s' % result.success_count) if result.failure_count: status.append('Failure %s' % result.failure_count) if result.error_count: status.append('Error %s' % result.error_count ) if status: status = ' '.join(status) else: status = 'none' return [ ('Start Time', startTime), ('Duration', duration), ('Status', status), ] def generateReport(self, test, result): report_attrs = self.getReportAttributes(result) generator = 'HTMLTestRunner %s' % __version__ stylesheet = self._generate_stylesheet() heading = self._generate_heading(report_attrs) report = self._generate_report(result) ending = self._generate_ending() output = self.HTML_TMPL % dict( title = saxutils.escape(self.title), generator = generator, stylesheet = stylesheet, heading = heading, report = report, ending = ending, ) self.stream.write(output.encode('utf8')) def _generate_stylesheet(self): return self.STYLESHEET_TMPL def _generate_heading(self, report_attrs): a_lines = [] for name, value in report_attrs: line = self.HEADING_ATTRIBUTE_TMPL % dict( name = saxutils.escape(name), value = saxutils.escape(value), ) a_lines.append(line) heading = self.HEADING_TMPL % dict( title = saxutils.escape(self.title), parameters = ''.join(a_lines), description = saxutils.escape(self.description), ) return heading def _generate_report(self, result): rows = [] sortedResult = self.sortResult(result.result) for cid, (cls, cls_results) in enumerate(sortedResult): # subtotal for a class np = nf = ne = 0 for n,t,o,e in cls_results: if n == 0: np += 1 elif n == 1: nf += 1 else: ne += 1 # format class description if cls.__module__ == "__main__": name = cls.__name__ else: name = "%s.%s" % (cls.__module__, cls.__name__) doc = cls.__doc__ and cls.__doc__.split("\n")[0] or "" desc = doc and '%s: %s' % (name, doc) or name row = self.REPORT_CLASS_TMPL % dict( style = ne > 0 and 'errorClass' or nf > 0 and 'failClass' or 'passClass', desc = desc, count = np+nf+ne, Pass = np, fail = nf, error = ne, cid = 'c%s' % (cid+1), ) rows.append(row) for tid, (n,t,o,e) in enumerate(cls_results): self._generate_report_test(rows, cid, tid, n, t, o, e) report = self.REPORT_TMPL % dict( test_list = ''.join(rows), count = str(result.success_count+result.failure_count+result.error_count), Pass = str(result.success_count), fail = str(result.failure_count), error = str(result.error_count), ) return report def _generate_report_test(self, rows, cid, tid, n, t, o, e): # e.g. 'pt1.1', 'ft1.1', etc has_output = bool(o or e) tid = (n == 0 and 'p' or 'f') + 't%s.%s' % (cid+1,tid+1) name = t.id().split('.')[-1] doc = t.shortDescription() or "" desc = doc and ('%s: %s' % (name, doc)) or name tmpl = has_output and self.REPORT_TEST_WITH_OUTPUT_TMPL or self.REPORT_TEST_NO_OUTPUT_TMPL # o and e should be byte string because they are collected from stdout and stderr? if isinstance(o,str): # TODO: some problem with 'string_escape': it escape \n and mess up formating # uo = unicode(o.encode('string_escape')) uo = o.decode('latin-1') else: uo = o if isinstance(e,str): # TODO: some problem with 'string_escape': it escape \n and mess up formating # ue = unicode(e.encode('string_escape')) ue = e.decode('latin-1') else: ue = e script = self.REPORT_TEST_OUTPUT_TMPL % dict( id = tid, output = saxutils.escape(uo+ue), ) row = tmpl % dict( tid = tid, Class = (n == 0 and 'hiddenRow' or 'none'), style = n == 2 and 'errorCase' or (n == 1 and 'failCase' or 'none'), desc = desc, script = script, status = self.STATUS[n], ) rows.append(row) if not has_output: return def _generate_ending(self): return self.ENDING_TMPL ############################################################################## # Facilities for running tests from the command line ############################################################################## # Note: Reuse unittest.TestProgram to launch test. In the future we may # build our own launcher to support more specific command line # parameters like test title, CSS, etc. class TestProgram(unittest.TestProgram): """ A variation of the unittest.TestProgram. Please refer to the base class for command line parameters. """ def runTests(self): # Pick HTMLTestRunner as the default test runner. # base class's testRunner parameter is not useful because it means # we have to instantiate HTMLTestRunner before we know self.verbosity. if self.testRunner is None: self.testRunner = HTMLTestRunner(verbosity=self.verbosity) unittest.TestProgram.runTests(self) main = TestProgram ############################################################################## # Executing this module from the command line ############################################################################## if __name__ == "__main__": main(module=None)
log.py
# coding=utf-8 import os import readconfig import logging from datetime import datetime import threading localReadConfig = readconfig.ReadConfig() class Log: def __init__(self): global logPath, resultPath, proDir proDir = readconfig.proDir resultPath = os.path.join(proDir, "output") if not os.path.exists(resultPath): os.mkdir(resultPath) logPath = os.path.join(resultPath, str(datetime.now().strftime("%Y%m%d%H%M%S"))) if not os.path.exists(logPath): os.mkdir(logPath) self.logger = logging.getLogger() self.logger.setLevel(logging.INFO) # defined handler handler = logging.FileHandler(os.path.join(logPath, "output.log")) # defined formatter formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) self.logger.addHandler(handler) def get_logger(self): """ get logger :return: """ return self.logger def build_start_line(self, case_no): """ write start line :return: """ self.logger.info("--------" + case_no + " START--------") def build_end_line(self, case_no): """ write end line :return: """ self.logger.info("--------" + case_no + " END--------") def build_case_line(self, case_name, code, msg): """ write test case line :param case_name: :param code: :param msg: :return: """ self.logger.info(case_name+" - Code:"+code+" - msg:"+msg) def get_logpath(self): return logPath def get_report_path(self): """ get report file path :return: """ report_path = os.path.join(logPath, "report.html") return report_path def get_result_path(self): """ get test result path :return: """ return logPath def write_result(self, result): """ :param result: :return: """ result_path = os.path.join(logPath, "report.txt") fb = open(result_path, "wb") try: fb.write(result) except IOError as ex: # 将FileNotFoundError给成了IOError(python版本问题) logger.error(str(ex)) class MyLog: log = None mutex = threading.Lock() def __init__(self): pass @staticmethod def get_log(): if MyLog.log is None: MyLog.mutex.acquire() MyLog.log = Log() MyLog.mutex.release() return MyLog.log if __name__ == "__main__": log = MyLog.get_log() logger = log.get_logger() logger.debug("test debug") logger.info("test info")
readconfig
import configparser import codecs import os import io pwd = os.path.dirname(os.path.abspath(__file__)) print(pwd) pwd1=os.path.dirname(pwd) print(pwd1) proDir = os.path.split(pwd1)[0] configPath = os.path.join(proDir, 'config\config.ini') print(configPath) class ReadConfig: def __init__(self): fd = io.open(configPath, "r", encoding='utf-8') data = fd.read() # remove BOM if data[:3] == codecs.BOM_UTF8: data = data[3:] file = codecs.open(configPath, "w") file.write(data) file.close() fd.close() self.cf = configparser.ConfigParser() self.cf.read(configPath,encoding='utf-8') def get_login(self,name): value = self.cf.get('login',name) return value def get_selection(self,name): value = self.cf.get('selection',name) return value def get_db(self,name): value= self.cf.get('db',name) return value def get_browserType(self,name): value = self.cf.get('browserType',name) return value if __name__=='__main__': print(ReadConfig().get_login('username'))
selenium_rewrite
# coding=utf-8 from selenium.webdriver.support.ui import WebDriverWait from selenium.common.exceptions import TimeoutException from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By # 判断元素是否可见 def is_visible(driver,locator,timeout=10): ''' :param driver: :param locator: xpath路径 :param timeout: :return:bool ''' try: WebDriverWait(driver,timeout).until(EC.visibility_of_element_located((By.XPATH,locator))) # visibility...参数为元组形式 return True except TimeoutException: return False # 判断元素是否存在 def isElementExist(method, element): ''' :param method: 寻找原始使用方法,不要实例化 :param element: 对应方法所对应的元素 :return:bool ''' flag = True try: method(element) except: flag = False finally: return flag
config
config.ini
[browserType] #browserName = Firefox browserName = Chrome #browserName = IE [login] username = shjdhi password = 123456 url = http://dvpub.aimap.net.cn/login [selection] year=2020 day_num=1 [db] ip=119.3.179.76 db_username=deepview db_password=FT!lyxbj0829 test_db=deepview-job polygon_code='212'
output
#result
功能:存放截图
testCase
test_script
Crawler,py
# coding=utf-8 from common.pub.browser_engine import BrowserEngine from common.bus.login import Login from common.bus.selectconfig import High_way_display,Timedate_select import time from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By from common.bus.screen_shot import Screenshot from common.pub.excelconfig import export from common.pub.readconfig import proDir import os class test(): def __init__(self): browser = BrowserEngine() self.driver = browser.open_browser() # self.driver = webdriver.Chrome() def run(self): driver=self.driver Login(driver).login_chrome() highway = High_way_display(driver) highway.select('拥堵') # 勾选 highway.select('施工') # 勾选 highway.select('占道行驶') # 勾选 # tm_selector = Timedate_select(driver) getattr=Screenshot(driver) date=[] # for i in range(1,8): # tm_selector.select_time(i) # 选择主界面下方的第n天 # time.sleep(2) clist = driver.find_elements_by_id('highway_list')[0].find_elements_by_tag_name('tr') n = len(clist) collect_time = "" if n==0: # print(date+"无采集数据") pass try: for index in range(1, n + 1): cl = driver.find_element_by_xpath('//*[@id="highway_list"]/tr[' + str(index) + ']') time_suffix = cl.find_elements_by_tag_name('td')[2].text driver.execute_script("arguments[0].scrollIntoView();", cl) cl.click() WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.XPATH, '//*[@id="highway_list"]/tr')) ) time.sleep(2) if driver.find_element_by_xpath('//*[@id="small-info-dlg"]/div[1]/div[3]/div[1]').text == collect_time: cl.click() time.sleep(5) title=getattr.get_title() location=getattr.get_location() caiji=getattr.get_caiji() recogintion=getattr.get_recognition() tmp=(title,location,caiji,recogintion) date.append(tmp) except Exception as e: print('str(e)') finally: fields=['title','location','caiji','recogintion'] output_path=os.path.join(proDir,'test.xls') export(fields, date, 'db', output_path) if __name__=='__main__': A=test() A.run()
unitest_method
test_check_collect_time.py
# coding=utf-8 import unittest import os import time from selenium import webdriver from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By from selenium.webdriver.support.wait import WebDriverWait from common.pub.browser_engine import BrowserEngine from common.bus.selectconfig import High_way_display,Timedate_select from common.bus.login import Login from common.pub.dbconfig import DbManipulate from common.bus.screen_shot import Screenshot import run1 import datetime from common.pub import readconfig from common.pub.excelconfig import export from common.pub.Log import MyLog as Log from common.pub import selenium_rewrite localReadConfig = readconfig.ReadConfig() result_path=run1.log_path class CheckCollectTime(unittest.TestCase): def setUp(self): browser = BrowserEngine() self.driver = browser.open_browser() # self.driver = webdriver.Chrome() Login(self.driver).login_chrome() highway = High_way_display(self.driver) highway.select('拥堵') #勾选 highway.select('施工') #勾选 highway.select('占道行驶') #勾选 log = Log.get_log() self.logger = log.get_logger() def test_case1(self): self.assertTrue(selenium_rewrite.is_visible(self.driver,"//div[@class='title']")) # @unittest.skip('n') def test_case2(self): driver=self.driver tm_selector = Timedate_select(driver) for i in range(1,8): tm_selector.select_time(i) # 选择主界面下方的第n天 time.sleep(2) clist = driver.find_elements_by_id('highway_list')[0].find_elements_by_tag_name('tr') n = len(clist) collect_time = "" if n==0: # print(date+"无采集数据") pass else: for index in range(1,n+1): cl = driver.find_element_by_xpath('//*[@id="highway_list"]/tr['+str(index)+']') time_suffix = cl.find_elements_by_tag_name('td')[2].text driver.execute_script("arguments[0].scrollIntoView();", cl) cl.click() WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.XPATH, '//*[@id="highway_list"]/tr')) ) time.sleep(2) if driver.find_element_by_xpath('//*[@id="small-info-dlg"]/div[1]/div[3]/div[1]').text == collect_time: cl.click() time.sleep(5) collect_time = driver.find_element_by_xpath('//*[@id="small-info-dlg"]/div[1]/div[3]/div[1]').text print(time_suffix,collect_time) self.assertTrue(time_suffix in collect_time,msg='失败原因:采集时间与列表事件时间不一致') time.sleep(1) # 数据流转对比测试用例 def test_case_2(self): driver=self.driver tm_selector = Timedate_select(driver) now_time = datetime.datetime.now() db = DbManipulate() pol_code= localReadConfig.get_db('polygon_code') for i in range(7): tm_selector.select_time(i+1) time.sleep(4) nowadays = str(driver.find_element_by_xpath("//ul[@id='dates_x']/li["+str(i+1)+']').text) midpath=os.path.join(result_path,'excel') if not os.path.exists(midpath): os.mkdir(midpath) innerpath = os.path.join(midpath,str(nowadays)) os.mkdir(innerpath) day1=(now_time + datetime.timedelta(days=-i)).strftime("%Y-%m-%d") day1 = '\'' + day1 + ' 00:00:00' + '\'' day2=(now_time + datetime.timedelta(days=-(i-1))).strftime("%Y-%m-%d") day2 = '\'' + day2 + ' 00:00:00' + '\'' results = db.query( "select b.id,FROM_UNIXTIME(floor(SUBSTRING(pic_file,-17,13)/1000)) a,t.polygon_code,check_block,check_traffic,check_work,check_blur,check_barrier,check_lowspeed,check_barrier,check_walk from pic_task t inner join pic_boxes_task b on b.pic_id = t.id where t.polygon_code=%s and check_rescue=-1 and check_repeat=1 and b.id not in (select id from(select b.id,FROM_UNIXTIME(round(SUBSTRING(pic_file,-17,13)/1000)) a,audit_time,t.polygon_code\ from pic_task t inner join pic_boxes_task b on b.pic_id = t.id where t.polygon_code=%s and check_block=-1 and check_traffic=-1 and check_work=-1 and check_blur=-1 and check_barrier and check_lowspeed=-1 and check_barrier=-1 and check_walk=-1 and audit_result=-1\ having a>%s and a<%s) a) having a>%s and a<%s" %(pol_code,pol_code,day1,day2,day1,day2)) fields = db.get_fields() caiji_list = Screenshot(driver).get_caiji_list() self.excp_export(fields, results, caiji_list, innerpath, nowadays) # 差值比较并导出excel def excp_export(self,fields,results, caiji_list, outputdir, nowadays): results = list(results) # day=caiji_list[0].split(' ')[0].encode('utf-8') # outputdir = os.path.join(Prodir,'outputs') if not os.path.exists(outputdir): os.mkdir(outputdir) # day_output=os.path.join(outputdir,str(datetime.now().strftime('%Y%m%d%H%M%S'))) # if not os.path.exists(day_output): # os.mkdir(day_output) outputpath1 = os.path.join(outputdir, nowadays + 'db.xls') outputpath2 = os.path.join(outputdir, nowadays + 'plat.xls') pic = [] res = [] for i in range(len(results)): time = str(results[i][1]) if caiji_list: if time in caiji_list: pic.append(results[i]) # results.remove(results[i]) caiji_list.remove(time) else: res.append(results[i]) else: res.append(results[i]) try: self.assertIsNotNone(caiji_list,'展示平台数据异常') finally: export(fields,res, 'db', outputpath1) export(fields,pic, 'plat', outputpath2) def tearDown(self): self.driver.quit() self.logger.info("Now, Close and quit the browser.")
caselist.txt
unitest_method/test_check_collect_time
run1
# coding=utf-8 import unittest import os from common.pub import HTMLTestRunner from common.pub.Log import MyLog as Log from common.pub import readconfig # def allTest(): # test_suite = unittest.TestSuite() # discover = unittest.TestLoader().discover( # start_dir=os.path.dirname(__file__), # 文件地址 # pattern="test_*.py", # 文件类型 # top_level_dir=None) # for test_name in discover: # test_suite.addTest(test_name) # # return test_suite # # log = Log.get_log() logger=log.get_logger() log_path=log.get_logpath() resultPath = log.get_report_path() # # # def run(): # fp = open(resultPath, 'wb') # runner = HTMLTestRunner.HTMLTestRunner(stream=fp, title='Test Report', description='Test Description') # # unittest.TextTestRunner(verbosity=2).run(allTest()) # runner.run(allTest()) class AllTest: def __init__(self): # global log, logger, resultPath, on_off # log = Log.get_log() # logger = log.get_logger() # resultPath = log.get_report_path() # on_off = localReadConfig.get_email("on_off") self.caseListFile = os.path.join(readconfig.proDir, "caselist.txt") self.caseFile = os.path.join(readconfig.proDir, "testCase") # self.caseFile = None self.caseList = [] # self.email = MyEmail.get_email() def set_case_list(self): """ set case list :return: """ fb = open(self.caseListFile) for value in fb.readlines(): data = str(value) if data != '' and not data.startswith("#"): self.caseList.append(data.replace("\n", "")) fb.close() def set_case_suite(self): """ set case suite :return: """ self.set_case_list() test_suite = unittest.TestSuite() suite_module = [] for case in self.caseList: case_name = case.split("/")[-1] print(case_name+".py") discover = unittest.defaultTestLoader.discover(self.caseFile, pattern=case_name + '.py', top_level_dir=None) suite_module.append(discover) if len(suite_module) > 0: for suite in suite_module: for test_name in suite: test_suite.addTest(test_name) else: return None return test_suite def run(self): """ run test :return: """ try: suit = self.set_case_suite() if suit is not None: logger.info("********TEST START********") fp = open(resultPath, 'wb') runner = HTMLTestRunner.HTMLTestRunner(stream=fp, title='Test Report', description='Test Description') runner.run(suit) else: logger.info("Have no case to test.") except Exception as ex: logger.error(str(ex)) finally: logger.info("*********TEST END*********") fp.close() if __name__ == "__main__": obj = AllTest() obj.run()