千家信息网

如何进行po+selenium+unittest自动化测试项目实战

发表于:2024-10-12 作者:千家信息网编辑
千家信息网最后更新 2024年10月12日,如何进行po+selenium+unittest自动化测试项目实战,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。一、项目工程目录:二
千家信息网最后更新 2024年10月12日如何进行po+selenium+unittest自动化测试项目实战

如何进行po+selenium+unittest自动化测试项目实战,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

一、项目工程目录:

二、具体工程文件代码:

1、新建一个包名:common(用于存放基本函数封装)

(1)在common包下新建一个base.py文件,作用:页面操作封装。base.py文件代码如下:

# coding=utf-8 """------------------------------------@Time : 2020/01/15@Auth : Anker@File : base.py@Description:页面操作封装@IDE  : PyCharm@Motto: Believe in yourself and persistence can make success!------------------------------------""" from selenium.webdriver.support.wait import WebDriverWaitfrom config.read_config import ReadConf  class BasePage(object):     # 读取config.ini配置文件,传入sections值    url = ReadConf()    # 传入sections模块    standard_url = url.readConf("sections")    # 这里传入sections模块中的url    base_url = standard_url['url']     def __init__(self, driver, test_url=base_url):        """        构造函数        :param driver        :param 传入url        """        self.driver = driver        self.url = test_url        # 设置全局元素隐式等待时间为10秒钟        self.driver.implicitly_wait(10)     def open_url(self):        """        打开url        :param:        """        url = self.url        self.driver.get(url)        title = self.driver.title        print("项目名称:", title + "2.6")        print("项目地址:", self.driver.current_url)     def back(self):        """        浏览器后退按钮        :param:        """        self.driver.back()     def forward(self):        """        浏览器前进按钮        :param:        """        self.driver.forward()     def close(self):        """        关闭并停止浏览器服务        :param:        """        self.driver.quit()     def find_element(self, *loc):        """        判断定位方式(常见的有8种获取元素的方法)        :param * loc        """        try:            WebDriverWait(self.driver, 20).until(lambda driver: driver.find_element(*loc).is_displayed())            return self.driver.find_element(*loc)        except:            print("元素在页面中未找到!", *loc)     def find_elements(self, *loc):        return self.driver.find_elements(*loc)     def input_content(self, loc, content):        """        文本框内容输入        :param loc        :param content        """        self.find_element(*loc).send_keys(content)     def send_keys(self, loc, value, clear_first=True, click_first=True):        try:            # getattr相当于self.loc            loc = getattr(self, "_%s" % loc)            if click_first:                self.mouse_click(loc)  # 调用鼠标点击事件方法            if clear_first:                self.mouse_clear(loc)  # 调用鼠标清理事件方法                self.find_element(*loc).send_keys(value)        except ArithmeticError:            print(u"%s 页面中未能找到 %s 元素" % (self, loc))     def mouse_clear(self, loc):        """        鼠标清理事件        :param loc        """        return self.find_element(*loc).clear()     def mouse_click(self, loc):        """        鼠标点击事件        :param loc        """        return self.find_element(*loc).click()     def script(self, src):        return self.driver.execute_script(src)     def switch_frame(self, loc):        return self.driver.switch_to_frame(loc)     def isElementPresent(self, element_xpath):        """        封装一个函数,用来判断页面某个值是否存在        :param element_xpath        """        try:            self.driver.find_element_by_xpath(element_xpath)            return True        except:            return False

(2)在common包下新建一个driver.py文件,作用:浏览器选择,默认为谷歌浏览器。driver.py文件代码如下:

# coding=utf-8 """------------------------------------@Time : 2020/01/15@Auth : Anker@File : driver.py@Description:浏览器选择,默认为谷歌浏览器@IDE  : PyCharm@Motto: Believe in yourself and persistence can make success!------------------------------------"""  from selenium import webdriverbrowser_type = "Chrome"  def open_browser():    """    浏览器选择(Selenium支持Chrome、Firefox、IE浏览器)    :param:    """    global driver    if browser_type == 'Firefox':        driver = webdriver.Firefox()    elif browser_type == 'Chrome':        driver = webdriver.Chrome()    elif browser_type == 'IE':        driver = webdriver.Ie()    elif browser_type == '':        driver = webdriver.Chrome()    return driver  if __name__ == '__main__':    driver = open_browser()

(3)在common包下新建一个HTMLTestRunner.py文件,作用:用于生成html报告文件。HTMLTestRunner.py文件代码如下:

#-*- coding: utf-8 -*-"""A TestRunner for use with the Python unit testing framework. Itgenerates 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 = ''    # run the test    runner.run(my_test_suite)------------------------------------------------------------------------Copyright (c) 2004-2007, Wai Yip TungAll rights reserved.Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditions aremet:* 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 "ASIS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITEDTO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR APARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNEROR 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, ORPROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDINGNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THISSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.""" # URL: http://tungwaiyip.info/software/HTMLTestRunner.html __author__ = "Wai Yip Tung"__version__ = "0.8.3"  """Change HistoryVersion 0.8.4 by GoverSky* Add sopport for 3.x* Add piechart for resultpiechart* Add Screenshot for selenium_case test* Add Retry on failedVersion 0.8.3* Prevent crash on class or module-level exceptions (Darren Wurf).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 
%(heading)s%(report)s%(ending)s""" # variables: (title, generator, stylesheet, heading, report, ending) # ------------------------------------------------------------------------ # Stylesheet # # alternatively use a for external style sheet, e.g. # STYLESHEET_TMPL = """""" # ------------------------------------------------------------------------ # Heading # HEADING_TMPL = """

%(title)s

%(parameters)s

%(description)s

""" # variables: (title, parameters, description) HEADING_ATTRIBUTE_TMPL = """

%(name)s: %(value)s

""" # variables: (name, value) # ------------------------------------------------------------------------ # Report # REPORT_TMPL = """

显示概要失败所有

%(test_list)s
测试组/测试用例 总数 通过 失败 错误 视图 错误截图
统计 %(count)s %(Pass)s %(fail)s %(error)s    
""" # variables: (test_list, count, Pass, fail, error) REPORT_CLASS_TMPL = r""" %(desc)s %(count)s %(Pass)s %(fail)s %(error)s 详情  """ # variables: (style, desc, count, Pass, fail, error, cid) REPORT_TEST_WITH_OUTPUT_TMPL = r"""
%(desc)s
%(status)s %(img)s""" # variables: (tid, Class, style, desc, status,img) REPORT_TEST_NO_OUTPUT_TMPL = r"""
%(desc)s
%(status)s %(img)s""" # variables: (tid, Class, style, desc, status,img) REPORT_TEST_OUTPUT_TMPL = r"""%(id)s: %(output)s""" # variables: (id, output) IMG_TMPL = r""" 显示截图
%(imgs)s
""" # ------------------------------------------------------------------------ # ENDING # ENDING_TMPL = """
 
""" # -------------------- The end of the Template class ------------------- def __getattribute__(self, item): value = object.__getattribute__(self, item) if PY3K: return value else: if isinstance(value, str): return value.decode("utf-8") else: return value 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, retry=0,save_last_try=True): 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 = [] self.retry = retry self.trys = 0 self.status = 0 self.save_last_try = save_last_try self.outputBuffer = StringIO.StringIO() def startTest(self, test): test.imgs = [] # test.imgs = getattr(test, "imgs", []) TestResult.startTest(self, test) self.outputBuffer.seek(0) self.outputBuffer.truncate() 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. if self.retry: if self.status == 1: self.trys += 1 if self.trys <= self.retry: if self.save_last_try: t = self.result.pop(-1) if t[0]==1: self.failure_count-=1 else: self.error_count -= 1 test=copy.copy(test) sys.stderr.write("Retesting... ") sys.stderr.write(str(test)) sys.stderr.write('..%d \n' % self.trys) doc = test._testMethodDoc or '' if doc.find('_retry')!=-1: doc = doc[:doc.find('_retry')] desc ="%s_retry:%d" %(doc, self.trys) if not PY3K: if isinstance(desc, str): desc = desc.decode("utf-8") test._testMethodDoc = desc test(self) else: self.status = 0 self.trys = 0 self.complete_output() def addSuccess(self, test): self.success_count += 1 self.status = 0 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 self.status = 1 TestResult.addError(self, test, err) _, _exc_str = self.errors[-1] output = self.complete_output() self.result.append((2, test, output, _exc_str)) if not getattr(test, "driver",""): pass else: try: driver = getattr(test, "driver") test.imgs.append(driver.get_screenshot_as_base64()) except Exception: pass 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 self.status = 1 TestResult.addFailure(self, test, err) _, _exc_str = self.failures[-1] output = self.complete_output() self.result.append((1, test, output, _exc_str)) if not getattr(test, "driver",""): pass else: try: driver = getattr(test, "driver") test.imgs.append(driver.get_screenshot_as_base64()) except Exception as e: pass 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=2, title=None, description=None, retry=0,save_last_try=False): self.stream = stream self.retry = retry self.save_last_try=save_last_try 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, self.retry, self.save_last_try) test(result) self.stopTime = datetime.datetime.now() self.generateReport(test, result) if PY3K: # for python3 # print('\nTime Elapsed: %s' % (self.stopTime - self.startTime),file=sys.stderr) output = '\nTime Elapsed: %s' % (self.stopTime - self.startTime) sys.stderr.write(output) else: 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 cls in rmap: 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(u'Pass%s' % result.success_count) if result.failure_count: status.append(u'Failure%s' % result.failure_count) if result.error_count: status.append(u'Error%s' % result.error_count) if status: status = ' '.join(status) else: status = 'none' return [ (u'开始时间', startTime), (u'耗时', duration), (u'状态', 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, ) if PY3K: self.stream.write(output.encode()) else: 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=name, value=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 if not PY3K: if isinstance(desc, str): desc = desc.decode("utf-8") 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=u''.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] if self.verbosity > 1: doc = t._testMethodDoc or '' else: doc = "" desc = doc and ('%s: %s' % (name, doc)) or name if not PY3K: if isinstance(desc, str): desc = desc.decode("utf-8") 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): # uo = unicode(o.encode('string_escape')) if PY3K: uo = o else: uo = o.decode('utf-8', 'ignore') else: uo = o if isinstance(e, str): # ue = unicode(e.encode('string_escape')) if PY3K: ue = e elif e.find("Error") != -1 or e.find("Exception") != -1: es = e.decode('utf-8', 'ignore').split('\n') es[-2] = es[-2].decode('unicode_escape') ue = u"\n".join(es) else: ue = e.decode('utf-8', 'ignore') else: ue = e script = self.REPORT_TEST_OUTPUT_TMPL % dict( id=tid, output=saxutils.escape(uo + ue), ) if getattr(t,'imgs',[]): # 判断截图列表,如果有则追加 tmp = u"" for i, img in enumerate(t.imgs): if i==0: tmp+=""" \n""" % img else: tmp+=""" \n""" % img imgs = self.IMG_TMPL % dict(imgs=tmp) else: imgs = u"""无截图""" row = tmpl % dict( tid=tid, Class=(n == 0 and 'hiddenRow' or 'none'), style=n == 2 and 'errorCase' or (n == 1 and 'failCase' or 'passCase'), desc=desc, script=script, status=self.STATUS[n], img=imgs, ) 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)

(4)在common包下新建一个login.py文件,作用:登录操作。login.py文件代码如下:

# coding=utf-8 """------------------------------------@Time : 2020/01/15@Auth : Anker@File : login.py@purpose:登录操作@IDE  : PyCharm@Motto: Believe in yourself and persistence can make success!------------------------------------""" from selenium.webdriver.common.by import Byfrom common.base import BasePage  class LoginPage(BasePage):     # 通过id的方式去定位用户名    username_loc = (By.ID, "login_username")    # 通过id的方式去定位用户密码    password_loc = (By.ID, "login_password")    # 通过xpath的方式去定位登录按钮    login_button_loc = (By.XPATH, "//*[text()='登 录']/..")     def input_username(self, username):        # 输入用户名        self.find_element(*self.username_loc).send_keys(username)     def input_password(self, password):        # 输入密码        self.find_element(*self.password_loc).send_keys(password)     def click_login_button(self):              # 点击登录按钮        self.find_element(*self.login_button_loc).click()     def login(self, username="18288888888", password="123456"):        self.open_url()        self.input_username(username)        self.input_password(password)        self.click_login_button()        return self.driver

(5)在common包下新建一个unit.py文件,作用:封装浏览器的启动和关闭的操作。unit.py文件代码如下:

# coding=utf-8 """------------------------------------@Time : 2020/01/15@Auth : Anker@File : unit.py@Description:封装浏览器的启动和关闭的操作@IDE  : PyCharm@Motto: Believe in yourself and persistence can make success!------------------------------------""" import unittestimport warnings  # 导入警告包,避免日志打印中出现报红的无关紧要的警告from selenium.webdriver.common.by import Byfrom common.driver import open_browser  class Unit(unittest.TestCase):     knowledge_graph_menu = (By.XPATH, '//*/span[text()="知识图谱"]')  # 点击知识图谱菜单    system_management_menu = (By.XPATH, '//*/span[text()="系统管理"]')  # 点击系统管理菜单     material_definition_menu = (By.XPATH, '//*[text()="物料定义"]')  # 点击物料定义菜单    material_name_text = (By.ID, "material_name")  # 输入物料名称    material_code_text = (By.ID, "material_code")  # 输入物料编码    material_unit_text = (By.ID, "material_unit")  # 输入物料单位     BOM_material_name_id = (By.ID, "material_sourceId")  # BOM关联的物料id    BOM_material_name_xpath = (By.XPATH, "//*[@id='material_sourceId']")  # BOM关联的物料xpath    BOM_definition_menu = (By.XPATH, '//*[text()="BOM定义"]')  # 点击BOM定义菜单     procedure_definition_menu = (By.XPATH, '//*[text()="工序定义"]')  # 点击工序定义菜单    procedure_name_text = (By.ID, "define_name")  # 输入工序名称    procedure_device_type_id = (By.ID, "define_typeId")  # 工序关联的设备类型id    procedure_device_type_xpath = (By.XPATH, "//*[@id='define_typeId']")  # 工序关联的设备类型xpath     workshop_definition_menu = (By.XPATH, '//*[text()="车间定义"]')  # 点击车间定义菜单    workshop_code_text = (By.ID, "define_code")  # 输入车间编码    workshop_name_text = (By.ID, "define_name")  # 输入车间名称    workshop_ip_text = (By.ID, "define_ip")  # 输入车间IP    workshop_management_text = (By.ID, "define_management")  # 输入车间负责人    workshop_name_id = (By.ID, "define_workshopId")  # 关联的车间id    workshop_name_xpath = (By.XPATH, "//*[@id='define_workshopId']")  # 关联的车间xpath     ipc_definition_menu = (By.XPATH, '//*[text()="终端定义"]')  # 点击终端定义菜单    ipc_name_text = (By.ID, "define_name")  # 输入终端名称    ipc_address_text = (By.ID, "define_address")  # 输入终端地址    ipc_ip_text = (By.ID, "define_ipcIp")  # 输入终端IP    ipc_remarks_text = (By.ID, "define_remark")  # 输入终端备注说明    ipc_name_id = (By.ID, "define_ipcList")  # 关联的工控机id    ipc_name_xpath = (By.XPATH, "//*[@id='define_ipcList']")  # 关联的工控机xpath     factory_modeling_menu = (By.XPATH, '//*[text()="工厂建模"]')  # 点击工厂建模菜单    factory_id = (By.ID, "define_factoryId")  # 关联的工厂id    factory_xpath = (By.XPATH, "//*[@id='define_factoryId']")  # 关联的工厂xpath    factory_name_text = (By.ID, "define_name")  # 输入工厂名称    factory_address_text = (By.ID, "define_address")  # 输入工厂地址     department_management_menu = (By.XPATH, '//*[text()="部门管理"]')  # 点击部门管理菜单    department_id = (By.ID, "define_deptId")  # 关联的部门id    department_xpath = (By.XPATH, "//*[@id='define_deptId']")  # 关联的部门xpath    department_name_text = (By.ID, "define_name")  # 输入部门名称     add_button = (By.XPATH, '//*[text()="新 增"]/..')  # 点击新增按钮    enter_xpath = (By.XPATH, "//*[@class='ant-select-search__field']")  # 按回车键    confirm_button = (By.XPATH, "//*[text()='确 定']/..")  # 点击确定按钮    # 新增设备时选择是否采集    yes_no_xpath = (By.XPATH, '//*[@id="define_needCollect"]/label[1]/span[text()="是"]')    # 新增工序时是否使用模具    tools_yes_no_xpath = (By.XPATH, '//*[@id="define_moudle"]/label[2]/span[text()="否"]')    # 物料选择自制或外购    self_control_xpath = (By.XPATH, '//*/span[text()="自制"]')    # 选择是否主工艺路线    process_route_yes_no_xpath = (By.XPATH, '//*[@id="define_techType"]/label[1]/span[text()="是"]')     device_definition_menu = (By.XPATH, '//*[text()="设备定义"]')  # 点击设备定义菜单    device_type_text = (By.ID, "define_name")  # 输入设备类型    device_list_menu = (By.XPATH, '//*[text()="设备列表"]')  # 点击设备列表菜单    device_code_text = (By.ID, "define_code")  # 输入设备编码    device_name_text = (By.ID, "define_name")  # 输入设备名称    device_name_id = (By.ID, "define_deviceIds")  # 关联设备名称id    device_name_xpath = (By.XPATH, "//*[@id='define_deviceIds']")  # 关联设备名称xpath     # 点击新增设备组页面的启用按钮    enable_xpath_text = (By.XPATH, '//*[@id="define_status"]/label[1]/span[text()="启用"]')     device_type_id = (By.ID, "define_deviceTypeId")  # 设备关联的设备类型id    device_type_xpath = (By.XPATH, "//*[@id='define_deviceTypeId']")  # 设备关联的设备类型xpath    devices_type_id = (By.ID, "define_type")  # 设备组关联的设备类型id    devices_type_xpath = (By.XPATH, "//*[@id='define_type']")  # 设备组关联的设备类型xpath     device_supplier_text = (By.ID, "define_brandModel")  # 输入设备供应商    devices_list_menu = (By.XPATH, '//*[text()="设备组列表"]')  # 点击设备组列表菜单    devices_list_code_text = (By.ID, "define_groupCode")  # 设备组编码    devices_list_name_text = (By.ID, "define_groupName")  # 设备组名称     process_route_menu = (By.XPATH, '//*[text()="工艺路线"]')  # 点击工艺路线菜单    process_route_material_name_id = (By.ID, "define_materialId")  # 工艺路线关联的物料id    process_route_material_name_xpath = (By.XPATH, "//*[@id='define_materialId']")  # 工艺路线关联的物料xpath    process_route_procedure_name_id = (By.ID, "define_procedure")  # 工艺路线关联的工序id    process_route_procedure_name_xpath = (By.XPATH, "//*[@id='define_procedure']")  # 工艺路线关联的工序xpath    process_route_device_name_id = (By.ID, "define_deviceDoList0")  # 工艺路线关联的设备id    process_route_device_name_xpath = (By.XPATH, "//*[@id='define_deviceDoList0']")  # 工艺路线关联的设备xpath     standard_box_count_xpath = (By.XPATH, '//*[@id="define_standarNum0"]')  # 标准框数量xpath     driver = None    # 使用@classmethod装饰器,setUpClass和 tearDownClass让每类执行只需要开启一次浏览器即可    # 使用@classmethod装饰器时不要把要测试的网页放置到setUpClass中那样执行完第一个用例时不会再次打开浏览器     @classmethod    def setUpClass(cls):        # 忽略告警信息        warnings.simplefilter('ignore', ResourceWarning)        cls.driver = open_browser()        cls.driver.implicitly_wait(10)        cls.driver.maximize_window()     @classmethod    def tearDownClass(cls):        cls.driver.quit()  if __name__ == '__main__':    # 调用unittest的TestSuite(),理解为管理case的一个容器(测试套件)    # unittest框架的自动化测试用例是以0-9、A-Z来排序执行测试用例    suite = unittest.TestSuite()    runner = unittest.TextTestRunner()

2、新建一个包名:config(用于存放配置文件、读取配置文件函数、业务变量)

(1)在config包下新建一个config.ini配置文件,作用:通过读取配置文件来获取变量。config.py文件代码如下:

# 通过读取配置文件来获取变量 [sections]url = https://www.baidu.com/

(2)在config包下新建一个read_config.py文件,作用:读取配置文件信息。read_config.py文件代码如下:

# coding=utf-8 """------------------------------------@Time : 2020/01/15@Auth : Anker@File : read_config.py@purpose:读取配置文件信息@IDE  : PyCharm@Motto: Believe in yourself and persistence can make success!------------------------------------""" import configparserimport os  class ReadConf:     def __init__(self):        current_path = os.path.dirname(os.path.relpath(__file__))        # 获取配置文件路径        config_path = os.path.join(current_path, "config.ini")         # 创建管理对象        self.conf = configparser.ConfigParser()        # 读ini文件        self.conf.read(config_path, encoding="utf-8")     def readConf(self, param):        # 获取所有的section        # sections = self.conf.sections()        # print(sections)        # 获取某个sections中的所有值,将其转化为字典        items = dict(self.conf.items(param))        return items  if __name__ == '__main__':    test = ReadConf()    url = test.readConf("sections")   # 传入sections的值    print('sections值为: ', url)

(3)在config包下新建一个variable.py文件,作用:业务关联的变量。variable.py文件代码如下:

# coding=utf-8 """------------------------------------@Time : 2020/01/15@Auth : Anker@File : variable.py@purpose:业务关联的变量@IDE  : PyCharm@Motto: Believe in yourself and persistence can make success!------------------------------------""" import timeimport random                                     # random模块用于随机数生成  # 获取系统当前时间,并在1~1000中随机生成一个动态变量数值# date_prefix = time.strftime("%Y-%m-%d %H:%M:%S") + "_编号" + str(random.randint(1, 1000))date_prefix = time.strftime("%Y%m%d") + "_编号" + str(random.randint(1, 1000)) factory_name = "中国" + date_prefixfactory_address = "浙江" + date_prefixdepartment_name = "测试部" + date_prefixworkshop_code = "chejian" + date_prefixworkshop_name = "车间" + date_prefixworkshop_ip = "192.168.1.1"workshop_management = "管理员"ipc_name = "终端" + date_prefixipc_address = "浙江" + date_prefixipc_ip = "1"device_type = "设备类型" + date_prefixdevice_code = "shebei" + date_prefixdevice_name = "设备" + date_prefixdevice_group_list_code = "设备组编码" + date_prefixdevice_group_list = "设备组" + date_prefixmaterial_name = "测试物料" + date_prefixmaterial_code = "wuliao" + date_prefixmaterial_code_path = '//*[text()="' + material_code + '"]'procedure_name = "测试工序" + date_prefixprocess_route = "主工艺路线"orderNo = "order" + date_prefixfirst_quality_contests = "首检" + date_prefixfirst_quality_types = "文本输入型"patrol_quality_contests = "巡检" + date_prefixpatrol_quality_types = "文本输入型"first_check_programme = "首检方案" + date_prefixpatrol_check_programme = "巡检方案" + date_prefixmould_warehouse = "模具仓库" + date_prefixmould_warehouse_address = "中国科技" + date_prefixtools_library = "工装仓库" + date_prefixtools_library_address = "中国科技" + date_prefixmould_storehouse = "模具库位" + date_prefixmould_storehouse_address = "中国科技" + date_prefixtool_storehouse = "工装库位" + date_prefixtool_storehouse_address = "中国科技" + date_prefixmould_code = "mould" + date_prefixmould_name = "模具" + date_prefixdevice_supplier = "供应商" + date_prefix

3、新建一个包名:report(用于存放测试报告和发送邮件函数)

(1)在report包下新建一个send_email.py文件,作用:发送邮件。send_email.py文件代码如下:

# coding=utf-8 """------------------------------------@Time : 2020/01/15@Auth : Anker@File : send_email.py@purpose:发送邮件@IDE  : PyCharm@Motto: Believe in yourself and persistence can make success!------------------------------------""" import smtplibfrom email.mime.multipart import MIMEMultipartfrom email.mime.text import MIMETextimport os  def send_email():    '''    发送测试报告到邮箱    :param:    :return:    '''     # ----------1.跟发件相关的参数------    # 发件服务器    smtp_server = "smtp.qq.com"    port = 25  # 端口    # 发送者账号    sender = "456789@qq.com"    # 发送者密码    password = "abc456789"    # 接收人    receiver = "456789@qq.com"     # ----------2.编辑邮件的内容--------    # 读文件    # os.getcwd()  # 获取当前路径    # os.path.abspath('..')  # 获取上级路径,一个.表示上级目录,两个.表示上两级目录    current_path = os.path.abspath('report')  # 读取report文件夹里的report.html    file_path = os.path.join(current_path, "report.html")     with open(file_path, "rb") as fp:        mail_body = fp.read()     message = MIMEMultipart()    message["from"] = sender                    # 发件人    message["to"] = receiver                    # 收件人    message["subject"] = "UI自动化测试"   # 主题     # 正文    # 通过decode()方法转换字符    body = MIMEText('

大家好:

UI自动化测试执行结果如下,' '详情请见附件

' + mail_body.decode(), "html", "utf-8") message.attach(body) # 附件 enclosure = MIMEText(mail_body, "base64", "utf-8") enclosure["Content-Type"] = "application/octet-stream" enclosure["Content-Disposition"] = 'attachment; filename="report.html"' message.attach(enclosure) # ----------3.发送邮件-------------- try: smtp = smtplib.SMTP() smtp.connect(smtp_server) # 连接服务器 smtp.login(sender, password) except: smtp = smtplib.SMTP_SSL(smtp_server, port) smtp.login(sender, password) # 登录 smtp.sendmail(sender, receiver, message.as_string()) # 发送 smtp.quit()

4、新建一个包名:test_case(用于存放测试用例)

(1)在test_case包下新建一个test_login.py文件,作用:登录测试用例。test_login.py文件代码如下:

# coding=utf-8 """------------------------------------@Time : 2020/01/15@Auth : Anker@File : test_login.py@purpose:测试用户登录@IDE  : PyCharm@Motto: Believe in yourself and persistence can make success!------------------------------------""" import unittestfrom common import unitfrom common.login import LoginPage  class LoginTest(unit.Unit):     def user_login_verify(self, username="", password=""):        LoginPage(self.driver).login(username, password)     def test_login1(self):        '''用户名、密码正确'''        self.user_login_verify(username="1828888888", password="000000")    def test_login2(self):        '''用户名正确,密码不正确'''        self.user_login_verify(username="1828888888", password="111")    def test_login3(self):        '''用户名不正确,密码正确'''        self.user_login_verify(username="aaa", password="000000")    def test_login4(self):        '''用户名、密码都不正确'''        self.user_login_verify(username="aaa", password="111111")    def test_login5(self):        '''用户名、密码为空'''        self.user_login_verify(username=" ", password=" ")    def test_login6(self):        '''用户名为空,密码不为空'''        self.user_login_verify(username=" ", password="090909")    def test_login7(self):        '''用户名不为空,密码为空'''        self.user_login_verify(username="123", password=" ")  if __name__ == '__main__':    unittest.main()

(2)在test_case包下新建一个test_PC.py文件,作用:业务测试用例(冒烟测试)。test_PC.py文件代码如下:

# coding=utf-8 """------------------------------------@Time : 2020/01/15@Auth : Anker@File : test_PC.py@purpose:冒烟测试用例@IDE  : PyCharm@Motto: Believe in yourself and persistence can make success!------------------------------------""" import timefrom selenium.webdriver.common.keys import Keys   # 获取键盘事件from common import unitfrom common.login import LoginPagefrom config import variable                       # 导入配置文件里的变量名  class TestCase(unit.Unit):     def test_case01_add_factory(self):        """        新增工厂        """        # 调用登录方法        LoginPage(self.driver).login()        time.sleep(2)        # 展开知识图谱        LoginPage(self.driver).find_element(*self.knowledge_graph_menu).click()        time.sleep(1)        # 进入工厂建模页面        LoginPage(self.driver).find_element(*self.factory_modeling_menu).click()        time.sleep(1)        # 点击"新增"按钮        LoginPage(self.driver).find_element(*self.add_button).click()        time.sleep(1)        # 输入工厂名称        LoginPage(self.driver).find_element(*self.factory_name_text).send_keys(variable.factory_name)        # 输入工厂地址        LoginPage(self.driver).find_element(*self.factory_address_text).send_keys(variable.factory_address)        # 点击"确定"按钮        LoginPage(self.driver).find_element(*self.confirm_button).click()        print("新增的工厂:", variable.factory_name)     def test_case02_add_department(self):        """        新增部门        """        time.sleep(2)        # 展开系统管理        LoginPage(self.driver).find_element(*self.system_management_menu).click()        time.sleep(1)        # 进入部门管理页面        LoginPage(self.driver).find_element(*self.department_management_menu).click()        time.sleep(1)        # 点击"新增"按钮        LoginPage(self.driver).find_element(*self.add_button).click()        time.sleep(1)        # 输入部门名称        LoginPage(self.driver).find_element(*self.department_name_text).send_keys(variable.department_name)        time.sleep(1)        # 关联的工厂名称        LoginPage(self.driver).find_element(*self.factory_id).click()        time.sleep(1)        LoginPage(self.driver).find_elements(*self.factory_xpath)[1].send_keys(variable.factory_name)        time.sleep(1)        LoginPage(self.driver).find_element(*self.enter_xpath).send_keys(Keys.ENTER)        time.sleep(1)        # 点击"确定"按钮        LoginPage(self.driver).find_element(*self.confirm_button).click()        print("新增的部门:", variable.department_name)     def test_case03_add_workshop(self):        """        新增车间        """        time.sleep(2)        # 展开知识图谱        LoginPage(self.driver).find_element(*self.knowledge_graph_menu).click()        time.sleep(1)        # 进入工厂建模页面        LoginPage(self.driver).find_element(*self.factory_modeling_menu).click()        time.sleep(1)        # 进入车间定义页面        LoginPage(self.driver).find_element(*self.workshop_definition_menu).click()        time.sleep(1)        # 点击"新增"按钮        LoginPage(self.driver).find_element(*self.add_button).click()        time.sleep(1)        # 输入车间编码        LoginPage(self.driver).find_element(*self.workshop_code_text).send_keys(variable.workshop_code)        # 输入车间名称        LoginPage(self.driver).find_element(*self.workshop_name_text).send_keys(variable.workshop_name)        time.sleep(1)        # 关联的部门名称        LoginPage(self.driver).find_element(*self.department_id).click()        time.sleep(1)        LoginPage(self.driver).find_elements(*self.department_xpath)[1].send_keys(variable.department_name)        time.sleep(1)        LoginPage(self.driver).find_element(*self.enter_xpath).send_keys(Keys.ENTER)        time.sleep(1)        # 输入车间IP        LoginPage(self.driver).find_element(*self.workshop_ip_text).send_keys(variable.workshop_ip)        # 输入车间负责人        LoginPage(self.driver).find_element(*self.workshop_management_text).send_keys(variable.workshop_management)        # 点击"确定"按钮        LoginPage(self.driver).find_element(*self.confirm_button).click()        print("新增的车间:", variable.workshop_name)     def test_case04_add_ipc(self):        """        新增终端        """        time.sleep(2)        # 进入终端定义页面        LoginPage(self.driver).find_element(*self.ipc_definition_menu).click()        time.sleep(1)        # 点击"新增"按钮        LoginPage(self.driver).find_element(*self.add_button).click()        time.sleep(1)        # 输入终端名称        LoginPage(self.driver).find_element(*self.ipc_name_text).send_keys(variable.ipc_name)        # 输入终端地址        LoginPage(self.driver).find_element(*self.ipc_address_text).send_keys(variable.ipc_address)        # 输入终端ip        LoginPage(self.driver).find_element(*self.ipc_ip_text).send_keys(variable.ipc_ip)        # 输入终端备注信息        LoginPage(self.driver).find_element(*self.ipc_remarks_text).send_keys("测试环境")        time.sleep(1)        # 点击"确定"按钮        LoginPage(self.driver).find_element(*self.confirm_button).click()        print("新增的终端:", variable.ipc_name)        print("终端ip:", variable.ipc_ip)     def test_case05_add_device_type(self):        """        新增设备类型        """        time.sleep(2)        # 进入设备定义页面        LoginPage(self.driver).find_element(*self.device_definition_menu).click()        time.sleep(1)        # 点击"新增"按钮        LoginPage(self.driver).find_element(*self.add_button).click()        time.sleep(1)        # 输入设备类型        LoginPage(self.driver).find_element(*self.device_type_text).send_keys(variable.device_type)        # 点击"确定"按钮        LoginPage(self.driver).find_element(*self.confirm_button).click()        print("新增的设备类型:", variable.device_type)     def test_case06_add_device(self):        """        新增设备        """        time.sleep(2)        # 进入设备列表页面        LoginPage(self.driver).find_element(*self.device_list_menu).click()        time.sleep(1)        # 点击"新增"按钮        LoginPage(self.driver).find_element(*self.add_button).click()        time.sleep(1)        # 输入设备编码        LoginPage(self.driver).find_element(*self.device_code_text).send_keys(variable.device_code)        # 输入设备名称        LoginPage(self.driver).find_element(*self.device_name_text).send_keys(variable.device_name)        time.sleep(1)        # 关联的设备类型        LoginPage(self.driver).find_element(*self.device_type_id).click()        time.sleep(1)        LoginPage(self.driver).find_elements(*self.device_type_xpath)[1].send_keys(variable.device_type)        time.sleep(1)        LoginPage(self.driver).find_elements(*self.enter_xpath)[1].send_keys(Keys.ENTER)        time.sleep(1)        # 绑定的工控机        LoginPage(self.driver).find_element(*self.ipc_name_id).click()        time.sleep(1)        LoginPage(self.driver).find_elements(*self.ipc_name_xpath)[1].send_keys(variable.ipc_name)        time.sleep(1)        LoginPage(self.driver).find_elements(*self.enter_xpath)[2].send_keys(Keys.ENTER)        time.sleep(1)        # 是否采集        LoginPage(self.driver).find_element(*self.yes_no_xpath).click()        time.sleep(1)        # 所属车间        LoginPage(self.driver).find_element(*self.workshop_name_id).click()        time.sleep(1)        LoginPage(self.driver).find_elements(*self.workshop_name_xpath)[1].send_keys(variable.workshop_name)        time.sleep(1)        LoginPage(self.driver).find_elements(*self.enter_xpath)[3].send_keys(Keys.ENTER)        time.sleep(1)        # 输入设备供应商        LoginPage(self.driver).find_element(*self.device_supplier_text).send_keys(variable.device_supplier)        time.sleep(1)        # 点击"确定"按钮        LoginPage(self.driver).find_element(*self.confirm_button).click()        print("新增的设备:", variable.device_name)        print("设备供应商:", variable.device_supplier)     def test_case07_add_device_group_list(self):        """        新增设备组        """        time.sleep(2)        # 进入设备组列表页面        LoginPage(self.driver).find_element(*self.devices_list_menu).click()        time.sleep(1)        # 点击"新增"按钮        LoginPage(self.driver).find_element(*self.add_button).click()        time.sleep(1)        # 输入设备组编码        LoginPage(self.driver).find_element(*self.devices_list_code_text).send_keys(variable.devices_list_code)        # 输入设备组名称        LoginPage(self.driver).find_element(*self.devices_list_name_text).send_keys(variable.devices_list_name)        time.sleep(1)        # 关联的设备        LoginPage(self.driver).find_element(*self.device_name_id).click()        time.sleep(1)        LoginPage(self.driver).find_elements(*self.device_name_xpath)[1].send_keys(variable.device_name)        time.sleep(1)        LoginPage(self.driver).find_elements(*self.enter_xpath)[1].send_keys(Keys.ENTER)        time.sleep(1)        # 点击"启用"按钮        LoginPage(self.driver).find_element(*self.enable_xpath_text).click()        time.sleep(1)        # 关联的设备类型        LoginPage(self.driver).find_element(*self.devices_type_id).click()        time.sleep(1)        LoginPage(self.driver).find_elements(*self.devices_type_xpath)[1].send_keys(variable.device_type)        time.sleep(1)        LoginPage(self.driver).find_elements(*self.enter_xpath)[2].send_keys(Keys.ENTER)        time.sleep(1)        # 绑定的工控机        LoginPage(self.driver).find_element(*self.ipc_name_id).click()        time.sleep(1)        LoginPage(self.driver).find_elements(*self.ipc_name_xpath)[1].send_keys(variable.ipc_name)        time.sleep(1)        LoginPage(self.driver).find_elements(*self.enter_xpath)[3].send_keys(Keys.ENTER)        time.sleep(1)        # 点击"启用"按钮(再次点击启用按钮的原因是:当选择绑定的工控机,按回车键后,需点击其它地方,才能将光标跳转到下个车间选择框)        LoginPage(self.driver).find_element(*self.enable_xpath_text).click()        time.sleep(1)        # 所属车间        LoginPage(self.driver).find_element(*self.workshop_name_id).click()        time.sleep(1)        LoginPage(self.driver).find_elements(*self.workshop_name_xpath)[1].send_keys(variable.workshop_name)        time.sleep(1)        LoginPage(self.driver).find_elements(*self.enter_xpath)[4].send_keys(Keys.ENTER)        time.sleep(1)        # 点击"确定"按钮        LoginPage(self.driver).find_element(*self.confirm_button).click()        print("新增的设备组:", variable.devices_list_name)     def test_case08_add_material(self):        """        新增物料        """        time.sleep(2)        # 进入物料定义页面        LoginPage(self.driver).find_element(*self.material_definition_menu).click()        time.sleep(1)        # 点击"新增"按钮        LoginPage(self.driver).find_element(*self.add_button).click()        time.sleep(1)        # 输入物料名称        LoginPage(self.driver).find_element(*self.material_name_text).send_keys(variable.material_name)        # 输入物料编码        LoginPage(self.driver).find_element(*self.material_code_text).send_keys(variable.material_code)        # 点击选择"自制"        LoginPage(self.driver).find_element(*self.self_control_xpath).click()        # 输入计量单位        LoginPage(self.driver).find_element(*self.material_unit_text).send_keys("kg")        # 点击"确定"按钮        LoginPage(self.driver).find_element(*self.confirm_button).click()        print("新增的物料:", variable.material_name)     def test_case09_add_BOM(self):        """        新增BOM        """        time.sleep(2)        # 进入BOM定义页面        LoginPage(self.driver).find_element(*self.BOM_definition_menu).click()        time.sleep(1)        # 点击"新增"按钮        LoginPage(self.driver).find_element(*self.add_button).click()        time.sleep(1)        # 关联的物料        LoginPage(self.driver).find_element(*self.BOM_material_name_id).click()        time.sleep(1)        LoginPage(self.driver).find_elements(*self.BOM_material_name_xpath)[1].send_keys(variable.material_name)        time.sleep(1)        LoginPage(self.driver).find_elements(*self.enter_xpath)[1].send_keys(Keys.ENTER)        time.sleep(1)        # 点击"确定"按钮        LoginPage(self.driver).find_element(*self.confirm_button).click()     def test_case10_add_procedure(self):        """        新增工序        """        time.sleep(2)        # 进入工序定义页面        LoginPage(self.driver).find_element(*self.procedure_definition_menu).click()        time.sleep(1)        # 点击"新增"按钮        LoginPage(self.driver).find_element(*self.add_button).click()        time.sleep(1)        # 输入工序名称        LoginPage(self.driver).find_element(*self.procedure_name_text).send_keys(variable.procedure_name)        time.sleep(1)        # 关联设备类型        LoginPage(self.driver).find_element(*self.procedure_device_type_id).click()        time.sleep(1)        LoginPage(self.driver).find_elements(*self.procedure_device_type_xpath)[1].send_keys(variable.device_type)        time.sleep(1)        LoginPage(self.driver).find_element(*self.enter_xpath).send_keys(Keys.ENTER)        time.sleep(1)        # 是否使用模具        LoginPage(self.driver).find_element(*self.tools_yes_no_xpath).click()        time.sleep(1)        # 点击"确定"按钮        LoginPage(self.driver).find_element(*self.confirm_button).click()        print("新增的工序:", variable.procedure_name)     def test_case11_add_process_route(self):        """        新增工艺路线        """        standard_box_count = str(variable.random.randint(1, 1000))  # 标准框数量随机生成        time.sleep(2)        # 进入工艺路线页面        LoginPage(self.driver).find_element(*self.process_route_menu).click()        time.sleep(1)        # 判断新增的物料是否配置过工艺路线        res = LoginPage(self.driver).isElementPresent(variable.material_code_path)        if res:            print("该物料已配置工艺路线")            time.sleep(1)            # 跳出工艺路线页面,进入知识图谱菜单            LoginPage(self.driver).find_element(*self.knowledge_graph_menu).click()        else:            # 点击"新增"按钮            LoginPage(self.driver).find_element(*self.add_button).click()            time.sleep(1)            # 关联物料名称            LoginPage(self.driver).find_element(*self.process_route_material_name_id).click()            time.sleep(1)            LoginPage(self.driver).find_elements(*self.process_route_material_name_xpath)[1].\                send_keys(variable.material_name)            time.sleep(1)            LoginPage(self.driver).find_elements(*self.enter_xpath)[1].send_keys(Keys.ENTER)            time.sleep(1)            # 选择是否主工艺路线            LoginPage(self.driver).find_element(*self.process_route_yes_no_xpath).click()            time.sleep(1)            # 关联的工序名称            LoginPage(self.driver).find_element(*self.process_route_procedure_name_id).click()            time.sleep(1)            LoginPage(self.driver).find_elements(*self.process_route_procedure_name_xpath)[1].\                send_keys(variable.procedure_name)            time.sleep(1)            LoginPage(self.driver).find_elements(*self.enter_xpath)[2].send_keys(Keys.ENTER)            time.sleep(1)            # 关联设备            LoginPage(self.driver).find_element(*self.process_route_device_name_id).click()            time.sleep(1)            LoginPage(self.driver).find_elements(*self.process_route_device_name_xpath)[1].\                send_keys(variable.device_name)            time.sleep(1)            LoginPage(self.driver).find_elements(*self.enter_xpath)[2].send_keys(Keys.ENTER)            time.sleep(1)            # 默认标准框数量            LoginPage(self.driver).find_element(*self.standard_box_count_xpath).click()            time.sleep(1)            LoginPage(self.driver).find_element(*self.standard_box_count_xpath).send_keys(standard_box_count)            time.sleep(1)            # 点击"确定"按钮            LoginPage(self.driver).find_element(*self.confirm_button).click()

5、新建一个run_all_test_case.py文件,作用:业务测试用例(新增工厂)。run_all_test_case.py文件代码如下:

# coding=utf-8 """------------------------------------@Time : 2020/01/10@Auth : Anker@File : run_all_test_case.py@purpose:执行所有测试用例@IDE  : PyCharm@Motto: Believe in yourself and persistence can make success!------------------------------------""" import unittestfrom common import HTMLTestRunnerimport osfrom report.send_email import send_email current_path = os.getcwd()  # 当前文件路径case_path = os.path.join(current_path, "test_case")  # 用例路径 # 存放报告路径report_path = os.path.join(current_path, "report")  # discover找出以test开头的用例def all_case():    discover = unittest.defaultTestLoader.discover(case_path, "test*.py")    return discover  if __name__ == "__main__":    # 测试报告为report.html    result_path = os.path.join(report_path, "report.html")     # 打开文件,把结果写进文件中,w,有内容的话,清空了再写进去    fp = open(result_path, "wb")     runner = HTMLTestRunner.HTMLTestRunner(stream=fp,                                           title="UI自动化测试报告",                                           description="用例执行情况")    # 调用all_case函数返回值    runner.run(all_case())     # 关闭刚才打开的文件    fp.close()    # 调用发送邮件方法    send_email()

关于如何进行po+selenium+unittest自动化测试项目实战问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注行业资讯频道了解更多相关知识。

0