全面详细的Python Selenium自动化测试实战项目指南

前言
之前的文章说过, 要写一篇自动化实战的文章, 这段时间比较忙再加回家过清明一直没有更新,今天整理一下实战项目的代码共大家学习。(注:项目是针对我们公司内部系统的测试,只能内部网络访问,外部网络无法访问)

问:

1.外部网络无法访问,代码也无法运行,那还看这个项目有啥用
2.如何学习本项目
3.如何学习自动化测试(python+selenium)
答:

1.其实代码并不重要,希望大家完完整整的看完这个项目后,自己会有思路有想法,学会这个项目的框架结构和设计思想,把这些能应用到自己的项目中,那么目的就达到了(项目中涉及到的一些公共方法是可以单独运行的,大家可以拿来执行用到自己的项目中)

2.首先希望大家带着目标来学习这个项目1. 项目的目录结构(每个目录中存放什么东西)2.项目如何使用框架(本项目使用的是unittest框架)3.设计模式是如何应用在本项目中的(本项目应用page
object设计模式)

3.个人而言

1)如果你没有任何的编程基础,建议先学习一门编程语言,包括环境的搭建,自己动手写代码,遇到问题多想多琢磨,这样一定会加深自己的印象。如果你有一定的编程基础那么直接看看python的基础语法和selenium就ok(我的自动化测试经验也有限,可能给不了大家太多的建议
,当然会的越多越好 呵!)

2)自己动手搭个框架,手写一个实战的项目,这时候你会发现你还有好多东西不会,那么线路就来了,哪里不会就去学哪里,边学边写,直到你的项目完成,再次回味就会发现你会了好多,当然不会的东西更多了因为你的思路慢慢的扩宽了,你会想到无人值守,集成等等的想法

3)可以参加培训机构的培训,说实话现在的培训机构越来越多,个人认为有些机构的老师确实是没什么水准的,因为他们教的是基础没有太多的拔高内容,但是有一点是好了,你可以很系统的学习一系列的自动化知识

ok 说了很多废话,大家不要介意!直接上项目
 

项目简介

  • 项目名称:**公司电子零售会员系统
  • 项目目的:实现电子零售会员系统项目自动化测试执行
  • 项目版本:v1.0
  • 项目目录

    Retail_TestPro
    Docs# 存放项目的相关文档        
    01测试计划
    02测试大纲
    03测试用例
    04测试报告
    05测试进度
    06技术文档
    07测试申请
    Package# 存放第三方插件
    HTMLTestRunner.py
    Retail
    Config
    init.py
    Conf.py# 读配置文件获取项目跟目录路径 并获取所有欲使用的目录文件的路径
    Config.ini# 存放项目跟目录的路径
    Data
    TestData
    init.py
    elementDate.xlsx# 存放项目中所有的元素信息及测试数据
    Email_receiver.txt# 存放邮件的接受者信息
    Report# 测试报告
    Image
    Fail# 存放用例执行失败时的截图
    Pass# 存放用例执行成功时的截图
    Log# 存放用例执行过程中的log信息
    TestReport# 存放测试用例执行完成后生成的测试报告
    Test_case# 测试用例信息
    Models # 存放一些公共方法
    Doconfini.py# 读配置文件
    Doexcel.py# 读excel文件
    Driver.py# 存放driver
    Log.py# 生成log
    Myunit.py# 继承unittest.Testcase
    Sendmail.py# 发送邮件
    Strhandle.py# 字符串处理
    Tcinfo.py# 测试用例基本信息
    Testreport.py# 测试报告
    Page_obj# 测试模块
    Activerule_page.py
    Base_page.py
    Company_page.py
    Createrule_page.py
    Memberquery_page.py
    Modifypw_page.py
    Pointquery_page.py
    ActiveRuleTc.py
    CompanyQueryTc.py
    CreateRuleTc.py
    LoginTc.py
    MemberQueryTc.py
    ModifyPwTc.py
    PointQueryTc.py
    runTc.py# 执行测试用例

    项目环境

  • 本版
  • python 36
  • pip insatll selenium
  • PyCharm 2017.2.4
  • Windows 10 10.0
  • HTMLTestRunner.py
  • 项目框架

  • unittest单元测试框架
  • pageobject 设计模式
  • UI对象库思想
  • 项目设计

  • 一个模块(被测项目的页面)对应一个py文件及一个测试类(测试文件)
  • 每一个测试页面(系统的页面)中存储页面元素及此页面中涉及到的功能
  • 每一个用例组合在一个测试类里面生成一个py文件
  • 项目目标

    我们在写自动化测试项目的时候一定要想好你的脚本都要哪些功能,页面元素平凡改动的时候是否需要大批量的修改脚本,及测试不同数据时是否也要修改脚本,那么能想到这些我们的初始目标差不多就有了

  • 生成测试用例执行结果报告
  • 生成测试用例执行日志
  • 用例执行失败或者执行完成后自动发送邮件报告
  • 用例执行失败或者成功时截取图片
  • 数据驱动(读取测试数据,减少脚本维护成本)
  •  

    项目代码

    config.ini # 存放项目跟路径

    [project]
     
    project_path = D:\Petrochina_Retail_Test_Project

    conf.py

     1 '''
     2 Code description:read config.ini, get path
     3 Create time:
     4 Developer:
     5 '''
     6 import os
     7 import sys
     8 from retail.test_case.models.doconfIni import DoConfIni
     9 
    10 # 获取当前路径
    11 currPath= \
    12     os.path.split(os.path.realpath(__file__))[0]
    13 
    14 # 读配置文件获取项目路径
    15 readConfig = \
    16     DoConfIni()
    17 proPath = \
    18     readConfig.getConfValue(os.path.join(currPath,'config.ini'),'project','project_path')
    19 
    20 # 获取日志路径
    21 logPath= \
    22     os.path.join(proPath,'retail','report','Log')
    23 
    24 # 测试用例路径
    25 tcPath = \
    26     os.path.join(proPath,'retail','test_case')
    27 
    28 # 获取报告路径
    29 reportPath= \
    30     os.path.join(proPath,'retail','report','TestReport')
    31 
    32 # 获取测试数据路径
    33 dataPath= \
    34     os.path.join(proPath,'retail','data','TestData')
    35 
    36 # 保存截图路径
    37 # 错误截图
    38 failImagePath = os.path.join(proPath, 'retail', 'report', 'image','fail')
    39 # 成功截图
    40 passImagePath = os.path.join(proPath, 'retail', 'report', 'image','pass')
    41 
    42 # 被调函数名称
    43 funcName = sys._getframe().f_code.co_name
    44 # 被调函数所在行号
    45 funcNo = sys._getframe().f_back.f_lineno
    46 
    47 # 被调函数所在文件名称
    48 funcFile= sys._getframe().f_code.co_filename

    elementData.xlsx # 存放所有的测试数据及元素

    一个excel文件,不方便贴里面内容(先过,别管里面是啥了 哈哈 后面再找吧)

    mail_receiver.txt# 存放邮件接收者的账号 , 可以添加多个账号以‘,’号分割

    **@qq.com 

    公共方法models下面的文件:

    doconfini.py

     1 '''
     2 Code description:read conf file
     3 Create time:
     4 Developer:
     5 '''
     6 
     7 import logging
     8 import configparser
     9 from retail.config.conf import *
    10 from retail.test_case.models.log import Logger
    11 
    12 log = Logger(__name__, CmdLevel=logging.INFO, FileLevel=logging.INFO)
    13 class DoConfIni(object):
    14 
    15     def __init__(self):
    16         """
    17 
    18         :param filename:
    19         """
    20         self.cf = configparser.ConfigParser()
    21     
    22     # 从ini文件中读数据
    23     def getConfValue(self,filename,section,name):
    24         """
    25 
    26         :param config:
    27         :param name:
    28         :return:
    29         """
    30         try:
    31             self.cf.read(filename)
    32             value = self.cf.get(section,name)
    33         except Exception as e:
    34             log.logger.exception('read file [%s] for [%s] failed , did not get the value' %(filename,section))
    35             raise e
    36         else:
    37             log.logger.info('read excel value [%s] successed! ' %value)
    38             return value
    39     # 向ini文件中写数据
    40     def writeConfValue(self,filename, section, name, value):
    41         """
    42 
    43         :param section: section
    44         :param name: value name
    45         :param value:  value
    46         :return: none
    47         """
    48         try:
    49             self.cf.add_section(section)
    50             self.cf.set(section, name, value)
    51             self.cf.write(open(filename, 'w'))
    52         except Exception :
    53             log.logger.exception('section %s has been exist!' %section)
    54             raise configparser.DuplicateSectionError(section)
    55         else:
    56             log.logger.info('write section'+section+'with value '+value+' successed!')
    57 
    58 if __name__ == '__main__':
    59     file_path = currPath
    60     print(file_path)
    61     read_config = DoConfIni()
    62 
    63     value = read_config.getConfValue(os.path.join(currPath,'config.ini'),'project','project_path')
    64     print(value)
    65 
    66     read_config.writeConfValue(os.path.join(currPath,'config.ini'),'tesesection', 'name', 'hello word')

    doexcel.py

     1 '''
     2 Code description:read excel.xlsx, get values
     3 Create time:
     4 Developer:
     5 '''
     6 
     7 import xlrd
     8 import os
     9 import logging
    10 from retail.config import conf
    11 from retail.test_case.models.log import Logger
    12 
    13 log = Logger(__name__, CmdLevel=logging.INFO, FileLevel=logging.INFO)
    14 
    15 class ReadExcel(object):
    16 
    17     def __init__(self,fileName='elementDate.xlsx',sheetName='elementsInfo'):
    18         """
    19 
    20         :param fileName:
    21         :param sheetName:
    22         """
    23         try:
    24             self.dataFile = os.path.join(conf.dataPath, fileName)
    25             self.workBook = xlrd.open_workbook(self.dataFile)
    26             self.sheetName = self.workBook.sheet_by_name(sheetName)
    27         except Exception:
    28             log.logger.exception('init class ReadExcel fail', exc_info=True)
    29             raise
    30         else:
    31             log.logger.info('initing class ReadExcel')
    32     # 读excel中的数据
    33     def readExcel(self,rownum,colnum):
    34         """
    35 
    36         :param rownum:
    37         :param colnum:
    38         :return:
    39         """
    40         try:
    41             value = self.sheetName.cell(rownum,colnum).value
    42         except Exception:
    43             log.logger.exception('read value from excel file fail', exc_info=True)
    44             raise
    45         else:
    46             log.logger.info('reading value [%s] from excel file [%s] completed' %(value, self.dataFile))
    47             return value
    48 
    49 if __name__ == '__main__':
    50     cellValue = ReadExcel().readExcel(1,3)
    51     print((cellValue))

    log.py

     1 '''
     2 Code description:log info
     3 Create time:
     4 Developer:
     5 '''
     6 
     7 import logging
     8 import time
     9 
    10 
    11 class Logger(object):
    12     def __init__(self, logger, CmdLevel=logging.INFO, FileLevel=logging.INFO):
    13         """
    14 
    15         :param logger:
    16         :param CmdLevel:
    17         :param FileLevel:
    18         """
    19         self.logger = logging.getLogger(logger)
    20         self.logger.setLevel(logging.DEBUG)  # 设置日志输出的默认级别
    21         # 日志输出格式
    22         fmt = logging.Formatter('%(asctime)s - %(filename)s:[%(lineno)s] - [%(levelname)s] - %(message)s')
    23         # 日志文件名称
    24         # self.LogFileName = os.path.join(conf.log_path, "{0}.log".format(time.strftime("%Y-%m-%d")))# %H_%M_%S
    25         currTime = time.strftime("%Y-%m-%d")
    26         self.LogFileName = r'D:\Petrochina_Retail_Test_Project\retail\report\Log\log'+currTime+'.log'
    27         # 设置控制台输出
    28         # sh = logging.StreamHandler()
    29         # sh.setFormatter(fmt)
    30         # sh.setLevel(CmdLevel)# 日志级别
    31 
    32         # 设置文件输出
    33         fh = logging.FileHandler(self.LogFileName)
    34         fh.setFormatter(fmt)
    35         fh.setLevel(FileLevel)# 日志级别
    36 
    37         # self.logger.addHandler(sh)
    38         self.logger.addHandler(fh)
    39 
    40     # def debug(self, message):
    41     #     """
    42     #
    43     #     :param message:
    44     #     :return:
    45     #     """
    46     #     self.logger.debug(message)
    47     #
    48     # def info(self,message):
    49     #     """
    50     #
    51     #     :param message:
    52     #     :return:
    53     #     """
    54     #     self.logger.info(message)
    55     #
    56     # def warn(self,message):
    57     #     """
    58     #
    59     #     :param message:
    60     #     :return:
    61     #     """
    62     #     self.logger.warning(message)
    63     #
    64     # def error(self,message):
    65     #     """
    66     #
    67     #     :param message:
    68     #     :return:
    69     #     """
    70     #     self.logger.error(message)
    71     #
    72     # def criti(self,message):
    73     #     """
    74     #
    75     #     :param message:
    76     #     :return:
    77     #     """
    78     #     self.logger.critical(message)
    79 
    80 if __name__ == '__main__':
    81     logger = Logger("fox",CmdLevel=logging.DEBUG, FileLevel=logging.DEBUG)
    82     logger.logger.debug("debug")
    83     logger.logger.log(logging.ERROR,'%(module)s %(info)s',{'module':'log日志','info':'error'}) #ERROR,log日志 error

    sendmail.py

      1 '''
      2 Code description:send email
      3 Create time:
      4 Developer:
      5 '''
      6 
      7 import smtplib
      8 from email.mime.text import MIMEText
      9 from email.header import Header
     10 import os
     11 from retail.config import conf
     12 from retail.test_case.models.log import Logger
     13 
     14 log = Logger(__name__)
     15 #   邮件发送接口
     16 class SendMail(object):
     17     '''
     18     邮件配置信息
     19     '''
     20     def __init__(self,
     21                  receiver,
     22                  subject='Retail 系统测试报告',
     23                  server='smtp.qq.com',
     24                  fromuser='281754043@qq.com',
     25                  frompassword='gifhhsbgqyovbhhc',
     26                  sender='281754043@qq.com'):
     27         """
     28 
     29         :param receiver:
     30         :param subject:
     31         :param server:
     32         :param fromuser:
     33         :param frompassword:
     34         :param sender:
     35         """
     36 
     37         self._server = server
     38         self._fromuser = fromuser
     39         self._frompassword = frompassword
     40         self._sender = sender
     41         self._receiver = receiver
     42         self._subject = subject
     43 
     44     def sendEmail(self, fileName):
     45         """
     46 
     47         :param filename:
     48         :return:
     49         """
     50         #   打开报告文件读取文件内容
     51         try:
     52             f = open(os.path.join(conf.reportPath, fileName), 'rb')
     53             fileMsg = f.read()
     54         except Exception:
     55             log.logger.exception('open or read file [%s] failed,No such file or directory: %s' %(fileName, conf.reportPath))
     56             log.logger.info('open and read file [%s] successed!' %fileName)
     57         else:
     58             f.close()
     59             #   邮件主题
     60             subject = 'Python test report' #
     61             #   邮件设置
     62             msg = MIMEText(fileMsg, 'html', 'utf-8')
     63             msg['subject'] = Header(subject, 'utf-8')
     64             msg['from'] = self._sender
     65         #   连接服务器,登录服务器,发送邮件
     66             try:
     67                 smtp = smtplib.SMTP()
     68                 smtp.connect(self._server)
     69                 smtp.login(self._fromuser, self._frompassword)
     70             except Exception:
     71                 log.logger.exception('connect [%s] server failed or username and password incorrect!' %smtp)
     72             else:
     73                 log.logger.info('email server [%s] login success!' %smtp)
     74                 try:
     75                     smtp.sendmail(self._sender, self._receiver, msg.as_string())
     76                 except Exception:
     77                     log.logger.exception('send email failed!')
     78                 else:
     79                     log.logger.info('send email successed!')
     80 
     81 
     82 #   从文件中读取邮件接收人信息
     83 def getReceiverInfo(fileName):
     84     '''
     85     :param filename: 读取接收邮件人信息
     86     :return: 接收邮件人信息
     87     '''
     88     try:
     89         openFile = open(os.path.join(conf.dataPath, fileName))
     90     except Exception:
     91         log.logger.exception('open or read file [%s] failed,No such file or directory: %s' %(fileName, conf.dataPath))
     92     else:
     93         log.logger.info('open file [%s] successed!' %fileName)
     94         for line in openFile:
     95             msg = [i.strip() for i in line.split(',')]
     96             log.logger.info('reading [%s] and got receiver value is [%s]' %(fileName, msg))
     97             return msg
     98 
     99 if __name__ == '__main__':
    100     readMsg=getReceiverInfo('mail_receiver.txt')
    101     sendmail = SendMail(readMsg)
    102     sendmail.sendEmail('2018-09-21 17_44_04.html')

    strhandle.py

     1 '''
     2 Code description: string handle
     3 Create time:
     4 Developer:
     5 '''
     6 
     7 import logging
     8 from retail.test_case.models.log import Logger
     9 
    10 log = Logger(__name__, CmdLevel=logging.INFO, FileLevel=logging.INFO)
    11 def strhandle(str):
    12     """
    13 
    14     :param str:
    15     :return:
    16     """
    17     #初始化字符、数字、空格、特殊字符的计数
    18     try:
    19         lowerCase = 0
    20         upperCase = 0
    21         number = 0
    22         other = 0
    23         for stritem in str:
    24          #如果在字符串中有小写字母,那么小写字母的数量+1
    25             if stritem.islower():
    26                 lowerCase += 1
    27             #如果在字符串中有数字,那么数字的数量+1
    28             elif stritem.isdigit():
    29                 number += 1
    30             elif stritem.isupper():# 大写字母
    31                 upperCase +=1
    32             #如果在字符串中有空格,那么空格的数量+1
    33             else:
    34                 other += 1
    35         return lowerCase, upperCase, number, other
    36     except Exception as e:
    37         log.logger.exception('string handle error , please check!', exc_info=True)
    38         raise e
    39 
    40 
    41 if __name__=='__main__':
    42     list = ['qwert','erwer']
    43     lowercase, uppercase, number, other = strhandle(list[0])
    44     print ("该字符串中的小写字母有:%d" %lowercase)
    45     print ("该字符串中的大写写字母有:%d" %uppercase)
    46     print ("该字符串中的数字有:%d" %number)
    47     print ("该字符串中的特殊字符有:%d" %other)

    testreport.py

     1 '''
     2 Code description:test report
     3 Create time:
     4 Developer:
     5 '''
     6 
     7 
     8 import time
     9 import logging
    10 import unittest
    11 from BeautifulReport import BeautifulReport
    12 import HTMLTestRunner
    13 from retail.config import conf
    14 from retail.test_case.models.log import Logger
    15 
    16 log = Logger(__name__, CmdLevel=logging.INFO, FileLevel=logging.INFO)
    17 # 用HTMLTestRunner 实现的测试报告
    18 def testreport():
    19     """
    20 
    21     :return:
    22     """
    23     currTime = time.strftime('%Y-%m-%d %H_%M_%S')
    24     fileName = conf.reportPath + r'\report' + currTime + '.html'
    25     try:
    26         fp = open(fileName, 'wb')
    27     except Exception :
    28         log.logger.exception('[%s] open error cause Failed to generate test report' %fileName)
    29     else:
    30         runner = HTMLTestRunner.HTMLTestRunner\
    31             (stream=fp, title='Retail sys测试报告',
    32                                                description='处理器:Intel(R) Core(TM) '
    33                                                            'i5-6200U CPU @ 2030GHz 2.40 GHz '
    34                                                 '内存:8G 系统类型: 64位 版本: windows 10 家庭中文版')
    35         log.logger.info('successed to generate test report [%s]' %fileName)
    36         return runner, fp, fileName
    37 #
    38 def addTc(TCpath = conf.tcPath, rule = '*TC.py'):
    39     """
    40 
    41     :param TCpath: 测试用例存放路径
    42     :param rule: 匹配的测试用例文件
    43     :return:  测试套件
    44     """
    45     discover = unittest.defaultTestLoader.discover(TCpath, rule)
    46 
    47     return discover
    48 # 用BeautifulReport模块实现测试报告
    49 def runTc(discover):
    50     """
    51 
    52     :param discover: 测试套件
    53     :return:
    54     """
    55     currTime = time.strftime('%Y-%m-%d %H_%M_%S')
    56     fileName = currTime+'.html'
    57     try:
    58         result = BeautifulReport(discover)
    59         result.report(filename=fileName, description='测试报告', log_path=conf.reportPath)
    60     except Exception:
    61         log.logger.exception('Failed to generate test report', exc_info=True)
    62     else:
    63         log.logger.info('successed to generate test report [%s]' % fileName)
    64         return fileName
    65 
    66 if __name__ == '__main__':
    67     testreport()
    68     suite = addTc(rule = '*TC.py')
    69     runTc(suite)

    driver.py

     1 '''
     2 Code description:save all driver info
     3 Create time:
     4 Developer:
     5 '''
     6 
     7 from selenium import webdriver
     8 import logging
     9 import sys
    10 from retail.test_case.models.log import Logger
    11 
    12 
    13 log = Logger(__name__, CmdLevel=logging.INFO, FileLevel=logging.INFO)
    14 class WDriver(object):
    15 
    16     # Firefox driver
    17     def fireFoxDriver(self):
    18         """
    19 
    20         :return:
    21         """
    22         try:
    23             self.driver = webdriver.Firefox()
    24         except Exception as e:
    25             log.logger.exception('FireFoxDriverServer.exe executable needs to be in PATH. Please download!', exc_info=True)
    26             raise e
    27         else:
    28             log.logger.info('%s:found the Firefox driver [%s] successed !' %(sys._getframe().f_code.co_name,self.driver))
    29             return self.driver
    30 
    31     # chrom driver
    32     def chromeDriver(self):
    33         """
    34 
    35         :return:
    36         """
    37         try:
    38             # option = webdriver.ChromeOptions()# 实现不打开浏览器 执行web自动化测试脚本
    39             # option.add_argument('headless')#
    40             # self.driver = webdriver.Chrome(chrome_options=option)
    41             self.driver = webdriver.Chrome()
    42         except Exception as e:
    43             log.logger.exception('ChromeDriverServer.exe executable needs to be in PATH. Please download!',
    44                                  exc_info=True)
    45             raise e
    46         else:
    47             log.logger.info('%s:found the chrome driver [%s] successed !' % (sys._getframe().f_code.co_name, self.driver))
    48             return self.driver
    49 
    50 
    51     # Ie driver
    52     def ieDriver(self):
    53         """
    54 
    55         :return:
    56         """
    57         try:
    58             self.driver = webdriver.Ie()
    59         except Exception as e:
    60             log.logger.exception('IEDriverServer.exe executable needs to be in PATH. Please download!',
    61                                  exc_info=True)
    62             raise e
    63         else:
    64             log.logger.info('%s:found the IE driver [%s] successed !' % (sys._getframe().f_code.co_name, self.driver))
    65             return self.driver
    66 
    67 
    68 if __name__ == '__main__':
    69     WDrive=WDriver()
    70     WDrive.fireFoxDriver()

    myunittest.py

     1 '''
     2 Code description:unittest framwork
     3 Create time:
     4 Developer:
     5 '''
     6 
     7 from retail.test_case.models.driver import WDriver
     8 import logging
     9 import unittest
    10 from retail.test_case.page_obj.login_page import LoginPage
    11 from retail.test_case.models.log import Logger
    12 from selenium import webdriver
    13 
    14 log = Logger(__name__, CmdLevel=logging.INFO, FileLevel=logging.INFO)
    15 class MyunitTest(unittest.TestCase):
    16     """
    17 
    18     """
    19 
    20     # add by xuechao at 2018.09.19
    21     @classmethod
    22     def setUpClass(cls): # 一个测试类(文件)执行一次打开浏览器, 节约每个用例打开一次浏览器的时间
    23 
    24         #cls.driver = WDriver().fireFoxDriver()
    25         cls.driver = WDriver().chromeDriver()
    26         cls.driver.maximize_window()
    27         log.logger.info('opened the browser successed!')
    28     # ----------------------------
    29 
    30     def setUp(self):
    31         """
    32 
    33         :return:
    34         """
    35         self.login = LoginPage(self.driver)
    36         self.login.open()
    37         log.logger.info('************************starting run test cases************************')
    38 
    39     def tearDown(self):
    40         """
    41 
    42         :return:
    43         """
    44         self.driver.refresh()
    45         log.logger.info('************************test case run completed************************')
    46 
    47     # add by linuxchao at 2018.09.19
    48     @classmethod
    49     def tearDownClass(cls):
    50         cls.driver.quit()
    51         log.logger.info('quit the browser success!')
    52     #----------------------------
    53 if __name__ == '__main__':
    54     unittest.main()

    目前为止,我需要的所有的公共方法都编写完了, 后期再需要别的方法可以加,下面我们就开始编写我们的测试用例,由于我们使用的是PageObject模式,那么我们需要设计一个basepage页面,所有的页面或者说模块全部继承这个basepage,basepage主要编写所有页面的公共方法

    base_page.py
     

      1 '''
      2 Code description: base page 封装一些公共方法
      3 Create time:
      4 Developer:
      5 '''
      6 from selenium.webdriver.support.wait import WebDriverWait
      7 from selenium.webdriver.support import expected_conditions as EC
      8 from selenium.webdriver.common.by import By
      9 import os
     10 import logging
     11 import sys
     12 from retail.test_case.models.log import Logger
     13 from retail.config import conf
     14 from retail.test_case.models.doexcel import ReadExcel
     15 
     16 eleData = ReadExcel() # 存储系统所有的元素数据
     17 testLoginData = ReadExcel('elementDate.xlsx', 'userNamePw') # 登录模块测试数据
     18 modifyPwData = ReadExcel('elementDate.xlsx', 'modifyPw') # 修改密码模块测试数据
     19 queryData = ReadExcel('elementDate.xlsx', 'queryData')
     20 log = Logger(__name__, CmdLevel=logging.INFO, FileLevel=logging.INFO)
     21 
     22 class BasePage(object):
     23 
     24     """主菜单"""
     25     menuList = \
     26         [(By.LINK_TEXT, eleData.readExcel(7, 3)), # 权限管理
     27         (By.LINK_TEXT, eleData.readExcel(8, 3)), # 会员档案
     28         (By.LINK_TEXT, eleData.readExcel(9, 3)), # 积分消费查询
     29         (By.LINK_TEXT, eleData.readExcel(10, 3)), # 功能演示
     30         (By.LINK_TEXT, eleData.readExcel(11, 3)), # 待办工作
     31         (By.LINK_TEXT, eleData.readExcel(12, 3)), # 报表
     32         (By.LINK_TEXT, eleData.readExcel(13, 3)), # 积分规则/活动查询
     33         (By.LINK_TEXT, eleData.readExcel(14, 3))] # 积分规则/活动申请
     34 
     35     def __init__(self, driver,url='http://11.11.164.134:9081/rmms/modules/ep.rmms.portal/login/login.jsp'):
     36         """
     37 
     38         :param driver:
     39         :param url:
     40         """
     41         self.driver = driver
     42         self.base_url = url
     43     def _open(self,url):
     44         """
     45 
     46         :param url:
     47         :return:
     48         """
     49         try:
     50             self.driver.get(url)
     51             self.driver.implicitly_wait(10)
     52         except Exception as e:
     53             log.logger.exception(e, exc_info=True)
     54             raise ValueError('%s address access error, please check!' %url)
     55         else:
     56             log.logger.info('%s is accessing address %s at line[46]' %(sys._getframe().f_code.co_name,url))
     57 
     58     def open(self):
     59         """
     60 
     61         :return:
     62         """
     63 
     64         self._open(self.base_url)
     65         log.logger.info('%s loading successed!' %self.base_url)
     66         return self.base_url
     67 
     68     # *loc 代表任意数量的位置参数
     69     def findElement(self, *loc):
     70         """
     71         查找单一元素
     72         :param loc:
     73         :return:
     74         """
     75         try:
     76             WebDriverWait(self.driver,10).until(EC.visibility_of_element_located(loc))
     77             # log.logger.info('The page of %s had already find the element %s'%(self,loc))
     78             # return self.driver.find_element(*loc)
     79         except Exception as e:
     80             log.logger.exception('finding element timeout!, details' ,exc_info=True)
     81             raise e
     82         else:
     83             log.logger.info('The page of %s had already find the element %s' % (self, loc))
     84             return self.driver.find_element(*loc)
     85 
     86     def findElements(self, *loc):
     87         """
     88         查找一组元素
     89         :param loc:
     90         :return:
     91         """
     92         try:
     93             WebDriverWait(self.driver,10).until(EC.visibility_of_element_located(loc))
     94             # log.logger.info('The page of %s had already find the element %s' % (self, loc))
     95             # return self.driver.find_elements(*loc)
     96         except Exception as e:
     97             log.logger.exception('finding element timeout!, details', exc_info=True)
     98             raise e
     99         else:
    100             log.logger.info('The page of %s had already find the element %s' % (self, loc))
    101             return self.driver.find_elements(*loc)
    102 
    103     def inputValue(self, inputBox, value):
    104         """
    105         后期修改其他页面直接调用这个函数
    106         :param inputBox:
    107         :param value:
    108         :return:
    109         """
    110         inputB = self.findElement(*inputBox)
    111         try:
    112             inputB.clear()
    113             inputB.send_keys(value)
    114         except Exception as e:
    115             log.logger.exception('typing value error!', exc_info=True)
    116             raise e
    117         else:
    118             log.logger.info('inputValue:[%s] is receiveing value [%s]' % (inputBox, value))
    119 
    120     # 获取元素数据
    121     def getValue(self, *loc):
    122         """
    123 
    124         :param loc:
    125         :return:
    126         """
    127         element = self.findElement(*loc)
    128         try:
    129             value = element.text
    130             #return value
    131         except Exception:
    132             #element = self.find_element_re(*loc) # 2018.09.21 for log
    133             value = element.get_attribute('value')
    134             log.logger.info('reading the element [%s] value [%s]' % (loc, value))
    135             return value
    136         except:
    137             log.logger.exception('read value failed', exc_info=True)
    138             raise Exception
    139         else:
    140             log.logger.info('reading the element [%s] value [%s]' % (loc,value))
    141             return value
    142 
    143     def getValues(self, *loc):
    144         """
    145 
    146         :param loc:
    147         :return:
    148         """
    149         value_list = []
    150         try:
    151             for element in self.findElements(*loc):
    152                 value = element.text
    153                 value_list.append(value)
    154         except Exception as e:
    155             log.logger.exception('read value failed', exc_info=True)
    156             raise e
    157         else:
    158             log.logger.info('reading the element [%s] value [%s]'% (loc,value_list))
    159             return value_list
    160 
    161     # 执行js脚本
    162     def jScript(self,src):
    163         """
    164 
    165         :param src:
    166         :return:
    167         """
    168         try:
    169             self.driver.excute_script(src)
    170         except Exception as e:
    171             log.logger.exception('execute js script [%s] failed ' %src)
    172             raise e
    173         else:
    174             log.logger.info('execute js script [%s] successed ' %src)
    175 
    176 
    177     # 判断元素是否存在
    178     def isElementExist(self, element):
    179         """
    180 
    181         :param element:
    182         :return:
    183         """
    184         try:
    185             WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located(element))
    186         except:
    187             # log.logger.exception('The element [%s] not exist', exc_info=True)
    188             return False
    189         else:
    190             # log.logger.info('The element [%s] have existed!' %element)
    191             return True
    192     # 截图
    193     def saveScreenShot(self, filename):
    194         """
    195 
    196         :param filename:
    197         :return:
    198         """
    199         list_value = []
    200 
    201         list = filename.split('.')
    202         for value in list:
    203             list_value.append(value)
    204         if list_value[1] == 'png' or list_value[1] == 'jpg' or list_value[1] == 'PNG' or list_value[1] == 'JPG':
    205             if 'fail' in list_value[0].split('_'):
    206                 try:
    207                     self.driver.save_screenshot(os.path.join(conf.failImagePath, filename))
    208                 except Exception:
    209                     log.logger.exception('save screenshot failed !', exc_info=True)
    210                 else:
    211                     log.logger.info('the file [%s]  save screenshot successed under [%s]' % (filename, conf.failImagePath))
    212             elif 'pass' in list_value[0]:
    213                 try:
    214                     self.driver.save_screenshot(os.path.join(conf.passImagePath, filename))
    215                 except Exception:
    216                     log.logger.exception('save screenshot failed !', exc_info=True)
    217                 else:
    218                     log.logger.info(
    219                         'the file [%s]  save screenshot successed under [%s]' % (filename, conf.passImagePath))
    220             else:
    221                 log.logger.info('save screenshot failed due to [%s] format incorrect' %filename)
    222         else:
    223             log.logger.info('the file name of [%s] format incorrect cause save screenshot failed, please check!' % filename)
    224 
    225     # 接受错误提示框
    226     def accept(self, *loc):
    227         """
    228 
    229         :return:
    230         """
    231         self.findElement(*loc).click()
    232         log.logger.info('closed the error information fram successed!')
    233 
    234 if __name__ == '__main__':
    235     pass

    #登录页面

     1 '''
     2 Code description: login page
     3 Create time:
     4 Developer:
     5 '''
     6 
     7 from selenium.webdriver.common.by import By
     8 import logging
     9 import sys
    10 from retail.test_case.page_obj.base_page import BasePage, eleData, testLoginData
    11 from retail.test_case.models.log import Logger
    12 
    13 log = Logger(__name__, CmdLevel=logging.INFO, FileLevel=logging.INFO)
    14 
    15 
    16 class LoginPage(BasePage):
    17 
    18     """用户名,密码,登录按钮,保存信息,错误提示"""
    19     userNameEle = (By.ID, eleData.readExcel(1, 3))
    20     passWordEle = (By.ID, eleData.readExcel(2, 3))
    21     loginBtnEle = (By.ID, eleData.readExcel(3, 3))
    22     saveInfoEle = (By.NAME, eleData.readExcel(4, 3))
    23     errorMessage = (By.ID, eleData.readExcel(5, 3))
    24     quitBtn = (By.ID, eleData.readExcel(6, 3))
    25 
    26     # 用户名和密码
    27     unpwData = \
    28         [[testLoginData.readExcel(1, 0), testLoginData.readExcel(1, 1)],# 正确的用户名和正确的密码
    29          [testLoginData.readExcel(2, 0), testLoginData.readExcel(2, 1)],# 错误的用户名和正确的密码
    30          [testLoginData.readExcel(3, 0), testLoginData.readExcel(3, 1)],# 空的用户名和正确的密码
    31          [testLoginData.readExcel(4, 0), testLoginData.readExcel(4, 1)],# 错误的用户名和错误的密码
    32          [testLoginData.readExcel(5, 0), testLoginData.readExcel(5, 1)],# 正确的用户名和空密码
    33          [testLoginData.readExcel(6, 0), testLoginData.readExcel(6, 1)],# 正确的用户名和错误的密码
    34          [testLoginData.readExcel(7, 0), testLoginData.readExcel(7, 1)]]# 空用户名和空密码
    35 
    36 
    37     # 登录按钮
    38     def clickLoginBtn(self):
    39         """
    40 
    41         :return:
    42         """
    43         element = self.findElement(*self.loginBtnEle)
    44         element.click()
    45         log.logger.info('%s ,logining....!' % sys._getframe().f_code.co_name)
    46     # 登录失败时提示
    47     def getFailedText(self):
    48         """
    49 
    50         :return:
    51         """
    52         info = self.findElement(*self.errorMessage).text
    53         log.logger.info('login failed : %s' %info)
    54         return info
    55 
    56     # 登录失败时弹出的alert
    57     def handleAlert(self):
    58         """
    59 
    60         :return:
    61         """
    62         try:
    63             alert = self.driver.switch_to_alert()
    64             text = alert.text
    65             alert.accept()
    66         except Exception:
    67             log.logger.exception('handle alert failed, please check the details' ,exc_info=True)
    68             raise
    69         else:
    70             log.logger.info('login failed ,%s handle alert successed alert info: %s!' %(sys._getframe().f_code.co_name, text))
    71             return text
    72 
    73     # 统一登录函数
    74     def loginFunc(self, username='rmln', password='qwert1234!@#'):
    75         """
    76         :param username:
    77         :param password:
    78         :return:
    79         """
    80         self.inputValue(self.userNameEle, username)
    81         self.inputValue(self.passWordEle, password)
    82         self.clickLoginBtn()
    83 
    84     # 清空输入框数据
    85     def clearValue(self, element):
    86 
    87         empty = self.findElement(*element)
    88         empty.clear()
    89         log.logger.info('emptying value.......')
    90 
    91 
    92     # 推出
    93     def quit(self):
    94         self.findElement(*self.quitBtn).click()
    95         log.logger.info('quit')
    96 
    97 if __name__ == '__main__':
    98     pass

    登录测试用例

    1 '''
      2 Code description:权限管理/个人设置/密码修改 testcase
      3 Create time:
      4 Developer:
      5 '''
      6 
      7 import time
      8 from retail.test_case.models.myunit import MyunitTest
      9 from retail.test_case.page_obj.modifypw_page import PrimaryMenu
     10 from retail.test_case.models.strhandle import strhandle
     11 
     12 class ModifyPw_TC(MyunitTest):
     13 
     14     """权限管理/个人设置/密码修改模块测试用例"""
     15 
     16     def test_menu_is_display(self):
     17         """主菜单校验"""
     18         self.login.loginFunc()
     19         menu = PrimaryMenu(self.driver)
     20         time.sleep(4)
     21         num = 0
     22         for menu_item in menu.menuList: # 循环遍历并断言菜单是否正确
     23             self.assertEqual(menu.menuList[num][1],(menu.findMenu(*menu_item).text),'菜单不存在')
     24             num=num+1
     25 
     26     def test_modify_password_len(self):
     27         """旧密码非空,新密码长度小于4位,确认密码非空,修改密码失败,弹窗提示"""
     28         self.login.loginFunc()
     29         menu = PrimaryMenu(self.driver)
     30         menu.modifyPwMenu() # 查找修改密码页面
     31         menu.modifyPw(menu.pwdList[0]) # 修改密码
     32         text = menu.errorDialog(menu.closeBtn)
     33         self.assertIn('密码长度至少 4 位!', text, '提示信息错误') # 密码长度不满足时断言提示信息
     34 
     35     def test_modify_password_strebgth(self):
     36         """旧密码非空,新密码长度大于4且强度不够,确认密码非空,修改密码失败,弹窗提示"""
     37         self.login.loginFunc()
     38         menu = PrimaryMenu(self.driver)
     39         menu.modifyPwMenu() # 查找修改密码页面
     40         menu.modifyPw(menu.pwdList[1]) # 修改密码
     41         text = menu.errorDialog(menu.closeBtn)
     42         self.assertIn('密码强度不够,请重新输入密码!', text, ' 密码强度不够,请重新输入密码!') # 密码强度不满足时断言提示信息
     43 
     44     def test_modify_password_incorrect(self):
     45         """旧密码不正确非空,新密码等于确认密码且满足条件,修改密码失败,弹窗提示"""
     46         self.login.loginFunc()
     47         menu = PrimaryMenu(self.driver)
     48         menu.modifyPwMenu() # 查找修改密码页面
     49         menu.modifyPw(menu.pwdList[2]) # 修改密码
     50         text = menu.errorDialog(menu.closeBtn)
     51         self.assertIn('旧密码输入错误!', text, '旧密码输入错误!') # 新密码和确认码不同时断言提示信息
     52 
     53     def test_modify_password_difference(self):
     54         """旧密码非空,新密码不等于确认密码且新密码满足条件,修改密码失败,弹窗提示"""
     55         self.login.loginFunc()
     56         menu = PrimaryMenu(self.driver)
     57         menu.modifyPwMenu() # 查找修改密码页面
     58         menu.modifyPw(menu.pwdList[3]) # 修改密码
     59         text = menu.errorDialog(menu.closeBtn)
     60         self.assertIn('两次输入的新密码不同!', text, '两次输入的新密码不同!') # 新密码和确认码不同时断言提示信息
     61 
     62     def test_modify_password_all_blank(self):
     63         """旧密码,新密码,确认密码任意为空,修改密码失败,弹窗提示"""
     64         self.login.loginFunc()
     65         menu = PrimaryMenu(self.driver)
     66         menu.modifyPwMenu() # 查找修改密码页面
     67         menu.modifyPw(menu.pwdList[4]) # 修改密码
     68         text = menu.errorDialog(menu.closeBtn)
     69         self.assertIn('该输入项的值不能为空!', text, ' 该输入项的值不能为空!') # 所有密码均为空时断言提示信息
     70 
     71     def test_modify_password(self):
     72         """循环校验提示信息"""
     73         self.login.loginFunc()
     74         menu = PrimaryMenu(self.driver)
     75         menu.modifyPwMenu() # 查找修改密码页面
     76         error_list = []
     77         for list in range(len(menu.pwdList)):
     78             menu.modifyPw(menu.pwdList[list])
     79             if menu.isElementExist(menu.errMessage):
     80                 text = menu.errorDialog(menu.closeBtn) # 这里只判断是否有提示框弹出,如有说明修改失败,没有或者其他提示框默认为修改成功
     81                 error_list.append(text)
     82             else:
     83                 self.assertTrue(menu.isElementExist(*menu.errMessage), 'error fram not exist, please open bug')
     84         self.assertEqual('密码长度至少 4 位!',error_list[0],'log infomation error!')
     85         self.assertEqual('密码强度不够,请重新输入密码!', error_list[1], 'log infomation error!')
     86         self.assertEqual('旧密码输入错误!', error_list[2], 'log infomation error!')
     87         self.assertEqual('两次输入的新密码不同!', error_list[3], 'log infomation error!')
     88         self.assertEqual('该输入项的值不能为空!', error_list[4], 'log infomation error!')
     89 
     90     def test_modifypw(self):
     91         """循环测试修改密码功能"""
     92         self.login.loginFunc()# 登录
     93         menu = PrimaryMenu(self.driver)
     94         menu.modifyPwMenu()  # 查找修改密码页面
     95         for item in menu.pwdList:
     96             menu.modifyPw(item)
     97             if menu.isElementExist(menu.errMessage):  # 如果存在提示框 再断言提示信息是否正确
     98                 if item[0] != '' and len(item[1]) < 4  and item[2] !='': # 新密码长度校验
     99                     text = menu.errorDialog(menu.closeBtn)
    100                     try:
    101                         self.assertEqual('密码长度至少 4 位!',text,'the message incorrect!')
    102                     except Exception:
    103                         menu.saveScreenShot('fail_密码长度.png')
    104                         raise
    105                 elif item[0] != '' and len(item[1]) >= 4 and item[2] !='': # 新密码强度校验 ['a', 'qwert', 'qwert'],
    106                     lowercase, uppercase, number, other=strhandle(item[1])
    107                     if lowercase > 0 and uppercase > 0 and number == 0 and other == 0: # 小写 大写
    108                         text = menu.errorDialog(menu.closeBtn)
    109                         self.assertIn('密码强度不够,请重新输入密码!', text, ' 密码强度不够,请重新输入密码!')
    110                     elif uppercase > 0 and other > 0 and number == 0 and lowercase == 0: # 大写 特殊字符
    111                         text = menu.errorDialog(menu.closeBtn)
    112                         self.assertIn('密码强度不够,请重新输入密码!', text, ' 密码强度不够,请重新输入密码!')
    113                     elif lowercase >0 and other > 0 and number == 0 and uppercase == 0: # 小写 特殊字符
    114                         text = menu.errorDialog(menu.closeBtn)
    115                         self.assertIn('密码强度不够,请重新输入密码!', text, ' 密码强度不够,请重新输入密码!')
    116                     elif lowercase == 0 and other == 0 and number > 0 and uppercase > 0:  # 大写 数字
    117                         text = menu.errorDialog(menu.closeBtn)
    118                         self.assertIn('密码强度不够,请重新输入密码!', text, ' 密码强度不够,请重新输入密码!')
    119                     elif lowercase > 0 and other == 0 and number > 0 and uppercase == 0:  # 小写 数字
    120                         text = menu.errorDialog(menu.closeBtn)
    121                         self.assertIn('密码强度不够,请重新输入密码!', text, ' 密码强度不够,请重新输入密码!')
    122                     elif lowercase > 0 and other == 0 and number == 0 and uppercase == 0:
    123                         text = menu.errorDialog(menu.closeBtn)
    124                         self.assertIn('密码强度不够,请重新输入密码!', text, ' 密码强度不够,请重新输入密码!')
    125                     elif lowercase == 0 and other > 0 and number == 0 and uppercase == 0:
    126                         text = menu.errorDialog(menu.closeBtn)
    127                         self.assertIn('密码强度不够,请重新输入密码!', text, ' 密码强度不够,请重新输入密码!')
    128                     elif lowercase == 0 and other == 0 and number > 0 and uppercase == 0:
    129                         text = menu.errorDialog(menu.closeBtn)
    130                         self.assertIn('密码强度不够,请重新输入密码!', text, ' 密码强度不够,请重新输入密码!')
    131                     elif lowercase == 0 and other == 0 and number == 0 and uppercase > 0:
    132                         text = menu.errorDialog(menu.closeBtn)
    133                         self.assertIn('密码强度不够,请重新输入密码!', text, ' 密码强度不够,请重新输入密码!')
    134                     elif item[0] != 'qwert1234!@#' and item[1] == item[2]:# >= 4
    135                         lowercase, uppercase, number, other = strhandle(item[1])
    136                         if (lowercase > 0 and uppercase > 0 and number > 0) or (
    137                                     lowercase > 0 and uppercase > 0 and other > 0) or (
    138                                     number > 0 and other > 0 and lowercase > 0) or (
    139                                     number > 0 and other > 0 and uppercase > 0):
    140                             text = menu.errorDialog(menu.closeBtn)
    141                             self.assertIn('旧密码输入错误!', text, '旧密码输入错误!')  # 新密码和确认码不同时断言提示信息
    142                     elif item[0] == 'qwert1234!@#$' and item[1] != item[2]:# and item[1] >= 4:
    143                         lowercase, uppercase, number, other = strhandle(item[1])
    144                         if (lowercase > 0 and uppercase > 0 and number > 0) or (
    145                                             lowercase > 0 and uppercase > 0 and other > 0) or (
    146                                             number > 0 and other > 0 and lowercase > 0) or (
    147                                             number > 0 and other > 0 and uppercase > 0):
    148                             text = menu.errorDialog(menu.closeBtn)
    149                             self.assertIn('两次输入的新密码不同!', text, ' 两次输入的新密码不同!')
    150                     else:
    151                         print('test value incorrect! please check it')
    152                 elif item[0] == '' or item[1] =='' or item[2] =='': # 输入项为空校验
    153                     text = menu.errorDialog(menu.closeBtn)
    154                     self.assertIn('该输入项的值不能为空!', text, ' 该输入项的值不能为空!')  # 所有密码均为空时断言提示信息
    155             else:
    156                 self.assertTrue(menu.isElementExist(menu.errMessage), 'error fram not exist, please check the test value or file bug')
    157 
    158 if __name__=='__main__':
    159     pass

    修改密码页面

     1 '''
      2 Code description:modify password page
      3 Create time:
      4 Developer:
      5 '''
      6 
      7 import logging
      8 import time
      9 from selenium.webdriver.common.by import By
     10 from selenium.webdriver.common.action_chains import ActionChains
     11 from retail.test_case.page_obj.base_page import BasePage, eleData, modifyPwData
     12 from retail.test_case.models.log import Logger
     13 
     14 log = Logger(__name__, CmdLevel=logging.INFO, FileLevel=logging.INFO)
     15 class PrimaryMenu(BasePage):
     16 
     17     """密码数据"""
     18     pwdList = \
     19         [[modifyPwData.readExcel(1, 0), modifyPwData.readExcel(1, 1), modifyPwData.readExcel(1, 2)],
     20          [modifyPwData.readExcel(2, 0), modifyPwData.readExcel(2, 1), modifyPwData.readExcel(2, 2)],
     21          [modifyPwData.readExcel(3, 0), modifyPwData.readExcel(3, 1), modifyPwData.readExcel(3, 2)],
     22          [modifyPwData.readExcel(4, 0), modifyPwData.readExcel(4, 1), modifyPwData.readExcel(4, 2)],
     23          [modifyPwData.readExcel(5, 0), modifyPwData.readExcel(5, 1), modifyPwData.readExcel(5, 2)]]
     24 
     25     """权限管理下拉菜单"""
     26     menuPersonal = (By.LINK_TEXT, eleData.readExcel(15, 3))
     27     menuModifyPwd = (By.LINK_TEXT, eleData.readExcel(16, 3))
     28 
     29     """密码修改"""
     30     oldPwd = (By.ID, eleData.readExcel(17, 3))
     31     newPwd = (By.ID, eleData.readExcel(18, 3))
     32     commitPwd = (By.ID, eleData.readExcel(19, 3))
     33 
     34     """错误提示框及确定"""
     35     errMessage = (By.XPATH, eleData.readExcel(20, 3))
     36     closeBtn = (By.CSS_SELECTOR, eleData.readExcel(21, 3))
     37 
     38     """密码说明"""
     39     readMe = (By.ID, eleData.readExcel(22, 3))
     40 
     41     """保存"""
     42     saveBtn = (By.XPATH, eleData.readExcel(23, 3))
     43 
     44     #   主菜单
     45     def findMenu(self,*menuList):
     46         """
     47 
     48         :param menu_list:
     49         :return:
     50         """
     51         return self.findElement(*menuList)
     52 
     53     #   旧密码输入框
     54     def inputOldPw(self, oldPwd=''):
     55         """"""
     56         try:
     57             self.findElement(*self.oldPwd).clear()
     58             self.findElement(*self.oldPwd).send_keys(oldPwd)
     59         except Exception:
     60             log.logger.exception('input Pw [%s] for oldPw [%s] fail' %(oldPwd, self.oldPwd))
     61             raise
     62         else:
     63             log.logger.info('inputing Pw [%s] for oldPw [%s] ' % (oldPwd, self.oldPwd))
     64     #   新密码输入框
     65     def inputNewPw(self, newPwd=''):
     66         """
     67 
     68         :param newPwd:
     69         :return:
     70         """
     71         try:
     72             self.findElement(*self.newPwd).clear()
     73             self.findElement(*self.newPwd).send_keys(newPwd)
     74         except Exception:
     75             log.logger.exception('input Pw [%s] for newPw [%s] fail' % (newPwd, self.newPwd))
     76             raise
     77         else:
     78             log.logger.info('inputing Pw [%s] for newPw [%s] ' % (newPwd, self.newPwd))
     79     #   确认密码输入框
     80     def inputConfirmPw(self, confirmPwd=''):
     81         """
     82 
     83         :param confirmPwd:
     84         :return:
     85         """
     86         try:
     87             self.findElement(*self.commitPwd).clear()
     88             self.findElement(*self.commitPwd).send_keys(confirmPwd)
     89         except Exception:
     90             log.logger.exception('input Pw [%s] for commitPw [%s] fail' %(confirmPwd, self.commitPwd))
     91             raise
     92         else:
     93             log.logger.info('inputing Pw [%s] for commitPw [%s] ' %(confirmPwd, self.commitPwd))
     94     #   保存
     95     def saveButton(self):
     96         """
     97 
     98         :return:
     99         """
    100         try:
    101             self.driver.implicitly_wait(5)
    102             clickbutton = self.findElement(*self.saveBtn)
    103             time.sleep(1)
    104             clickbutton.click()
    105         except Exception:
    106             log.logger.exception('click save button fail')
    107             raise
    108         else:
    109             log.logger.info('clciking the button')
    110 
    111     #   修改密码功能菜单
    112     def modifyPwMenu(self):
    113         """
    114 
    115         :return:
    116         """
    117         try:
    118             self.findElement(*self.menuList[0]).click()
    119             self.findElement(*self.menuPersonal).click()
    120             self.findElement(*self.menuModifyPwd).click()
    121         except Exception:
    122             log.logger.exception('not found menu [%s]-[%s]-[%s]' %(self.menuList[0], self.menuPersonal, self.menuModifyPwd))
    123             raise
    124         else:
    125             log.logger.info('finding menu [%s]-[%s]-[%s]' %(self.menuList[0], self.menuPersonal, self.menuModifyPwd))
    126             self.driver.implicitly_wait(2)
    127 
    128     #   修改密码
    129     def modifyPw(self, list):
    130         """
    131 
    132         :param list:
    133         :return:
    134         """
    135         try:
    136             self.inputOldPw(list[0])
    137             self.inputNewPw(list[1])
    138             self.inputConfirmPw(list[2])
    139             self.saveButton()
    140         except Exception:
    141             log.logger.exception('input oldpw/newpw/commitpw [%s]/[%s]/[%s] fail' %(list[0], list[1], list[2]))
    142             raise
    143         else:
    144             log.logger.info('modifing pw [%s]/[%s]/[%s]' %(list[0], list[1], list[2]))
    145 
    146     #   错误提示框
    147     def errorDialog(self, commit_btn = (By.ID,'unieap_form_Button_1_unieap_input')):
    148         """
    149         :type commit_btn: 元祖
    150         """
    151 
    152         try:
    153             messages_frame = self.findElement(*self.errMessage)
    154             text = messages_frame.text
    155             element = self.findElement(*commit_btn)
    156             time.sleep(2)
    157             action = ActionChains(self.driver)
    158             action.move_to_element(element).perform()
    159             time.sleep(2)
    160             element.click()
    161             action.reset_actions() # 释放鼠标
    162         except Exception:
    163             log.logger.exception('close errMsgFram [%s] or get text [%s]fail' %(self.errMessage))
    164             raise
    165         else:
    166             log.logger.info('close errMsgFram [%s] and get text [%s] success' %(self.errMessage, text))
    167             return text
    168 
    169     # 关闭提示框
    170     def closeErrMsg(self, element):
    171         try:
    172             ele = self.findElement(*element)
    173             action = ActionChains(self.driver)
    174             action.move_to_element(ele).perform()
    175             time.sleep(2)
    176             ele.click()
    177             action.reset_actions()
    178         except Exception:
    179             log.logger.exception('close the err msg ifram fail', exc_info=True)
    180             raise
    181         else:
    182             log.logger.info('closing the err msg ifram success!')
    183 
    184 if __name__ == '__main__':
    185     pass

    修改密码测试用例

    ​
     1 '''
      2 Code description:权限管理/个人设置/密码修改 testcase
      3 Create time:
      4 Developer:
      5 '''
      6 
      7 import time
      8 from retail.test_case.models.myunit import MyunitTest
      9 from retail.test_case.page_obj.modifypw_page import PrimaryMenu
     10 from retail.test_case.models.strhandle import strhandle
     11 
     12 class ModifyPw_TC(MyunitTest):
     13 
     14     """权限管理/个人设置/密码修改模块测试用例"""
     15 
     16     def test_menu_is_display(self):
     17         """主菜单校验"""
     18         self.login.loginFunc()
     19         menu = PrimaryMenu(self.driver)
     20         time.sleep(4)
     21         num = 0
     22         for menu_item in menu.menuList: # 循环遍历并断言菜单是否正确
     23             self.assertEqual(menu.menuList[num][1],(menu.findMenu(*menu_item).text),'菜单不存在')
     24             num=num+1
     25 
     26     def test_modify_password_len(self):
     27         """旧密码非空,新密码长度小于4位,确认密码非空,修改密码失败,弹窗提示"""
     28         self.login.loginFunc()
     29         menu = PrimaryMenu(self.driver)
     30         menu.modifyPwMenu() # 查找修改密码页面
     31         menu.modifyPw(menu.pwdList[0]) # 修改密码
     32         text = menu.errorDialog(menu.closeBtn)
     33         self.assertIn('密码长度至少 4 位!', text, '提示信息错误') # 密码长度不满足时断言提示信息
     34 
     35     def test_modify_password_strebgth(self):
     36         """旧密码非空,新密码长度大于4且强度不够,确认密码非空,修改密码失败,弹窗提示"""
     37         self.login.loginFunc()
     38         menu = PrimaryMenu(self.driver)
     39         menu.modifyPwMenu() # 查找修改密码页面
     40         menu.modifyPw(menu.pwdList[1]) # 修改密码
     41         text = menu.errorDialog(menu.closeBtn)
     42         self.assertIn('密码强度不够,请重新输入密码!', text, ' 密码强度不够,请重新输入密码!') # 密码强度不满足时断言提示信息
     43 
     44     def test_modify_password_incorrect(self):
     45         """旧密码不正确非空,新密码等于确认密码且满足条件,修改密码失败,弹窗提示"""
     46         self.login.loginFunc()
     47         menu = PrimaryMenu(self.driver)
     48         menu.modifyPwMenu() # 查找修改密码页面
     49         menu.modifyPw(menu.pwdList[2]) # 修改密码
     50         text = menu.errorDialog(menu.closeBtn)
     51         self.assertIn('旧密码输入错误!', text, '旧密码输入错误!') # 新密码和确认码不同时断言提示信息
     52 
     53     def test_modify_password_difference(self):
     54         """旧密码非空,新密码不等于确认密码且新密码满足条件,修改密码失败,弹窗提示"""
     55         self.login.loginFunc()
     56         menu = PrimaryMenu(self.driver)
     57         menu.modifyPwMenu() # 查找修改密码页面
     58         menu.modifyPw(menu.pwdList[3]) # 修改密码
     59         text = menu.errorDialog(menu.closeBtn)
     60         self.assertIn('两次输入的新密码不同!', text, '两次输入的新密码不同!') # 新密码和确认码不同时断言提示信息
     61 
     62     def test_modify_password_all_blank(self):
     63         """旧密码,新密码,确认密码任意为空,修改密码失败,弹窗提示"""
     64         self.login.loginFunc()
     65         menu = PrimaryMenu(self.driver)
     66         menu.modifyPwMenu() # 查找修改密码页面
     67         menu.modifyPw(menu.pwdList[4]) # 修改密码
     68         text = menu.errorDialog(menu.closeBtn)
     69         self.assertIn('该输入项的值不能为空!', text, ' 该输入项的值不能为空!') # 所有密码均为空时断言提示信息
     70 
     71     def test_modify_password(self):
     72         """循环校验提示信息"""
     73         self.login.loginFunc()
     74         menu = PrimaryMenu(self.driver)
     75         menu.modifyPwMenu() # 查找修改密码页面
     76         error_list = []
     77         for list in range(len(menu.pwdList)):
     78             menu.modifyPw(menu.pwdList[list])
     79             if menu.isElementExist(menu.errMessage):
     80                 text = menu.errorDialog(menu.closeBtn) # 这里只判断是否有提示框弹出,如有说明修改失败,没有或者其他提示框默认为修改成功
     81                 error_list.append(text)
     82             else:
     83                 self.assertTrue(menu.isElementExist(*menu.errMessage), 'error fram not exist, please open bug')
     84         self.assertEqual('密码长度至少 4 位!',error_list[0],'log infomation error!')
     85         self.assertEqual('密码强度不够,请重新输入密码!', error_list[1], 'log infomation error!')
     86         self.assertEqual('旧密码输入错误!', error_list[2], 'log infomation error!')
     87         self.assertEqual('两次输入的新密码不同!', error_list[3], 'log infomation error!')
     88         self.assertEqual('该输入项的值不能为空!', error_list[4], 'log infomation error!')
     89 
     90     def test_modifypw(self):
     91         """循环测试修改密码功能"""
     92         self.login.loginFunc()# 登录
     93         menu = PrimaryMenu(self.driver)
     94         menu.modifyPwMenu()  # 查找修改密码页面
     95         for item in menu.pwdList:
     96             menu.modifyPw(item)
     97             if menu.isElementExist(menu.errMessage):  # 如果存在提示框 再断言提示信息是否正确
     98                 if item[0] != '' and len(item[1]) < 4  and item[2] !='': # 新密码长度校验
     99                     text = menu.errorDialog(menu.closeBtn)
    100                     try:
    101                         self.assertEqual('密码长度至少 4 位!',text,'the message incorrect!')
    102                     except Exception:
    103                         menu.saveScreenShot('fail_密码长度.png')
    104                         raise
    105                 elif item[0] != '' and len(item[1]) >= 4 and item[2] !='': # 新密码强度校验 ['a', 'qwert', 'qwert'],
    106                     lowercase, uppercase, number, other=strhandle(item[1])
    107                     if lowercase > 0 and uppercase > 0 and number == 0 and other == 0: # 小写 大写
    108                         text = menu.errorDialog(menu.closeBtn)
    109                         self.assertIn('密码强度不够,请重新输入密码!', text, ' 密码强度不够,请重新输入密码!')
    110                     elif uppercase > 0 and other > 0 and number == 0 and lowercase == 0: # 大写 特殊字符
    111                         text = menu.errorDialog(menu.closeBtn)
    112                         self.assertIn('密码强度不够,请重新输入密码!', text, ' 密码强度不够,请重新输入密码!')
    113                     elif lowercase >0 and other > 0 and number == 0 and uppercase == 0: # 小写 特殊字符
    114                         text = menu.errorDialog(menu.closeBtn)
    115                         self.assertIn('密码强度不够,请重新输入密码!', text, ' 密码强度不够,请重新输入密码!')
    116                     elif lowercase == 0 and other == 0 and number > 0 and uppercase > 0:  # 大写 数字
    117                         text = menu.errorDialog(menu.closeBtn)
    118                         self.assertIn('密码强度不够,请重新输入密码!', text, ' 密码强度不够,请重新输入密码!')
    119                     elif lowercase > 0 and other == 0 and number > 0 and uppercase == 0:  # 小写 数字
    120                         text = menu.errorDialog(menu.closeBtn)
    121                         self.assertIn('密码强度不够,请重新输入密码!', text, ' 密码强度不够,请重新输入密码!')
    122                     elif lowercase > 0 and other == 0 and number == 0 and uppercase == 0:
    123                         text = menu.errorDialog(menu.closeBtn)
    124                         self.assertIn('密码强度不够,请重新输入密码!', text, ' 密码强度不够,请重新输入密码!')
    125                     elif lowercase == 0 and other > 0 and number == 0 and uppercase == 0:
    126                         text = menu.errorDialog(menu.closeBtn)
    127                         self.assertIn('密码强度不够,请重新输入密码!', text, ' 密码强度不够,请重新输入密码!')
    128                     elif lowercase == 0 and other == 0 and number > 0 and uppercase == 0:
    129                         text = menu.errorDialog(menu.closeBtn)
    130                         self.assertIn('密码强度不够,请重新输入密码!', text, ' 密码强度不够,请重新输入密码!')
    131                     elif lowercase == 0 and other == 0 and number == 0 and uppercase > 0:
    132                         text = menu.errorDialog(menu.closeBtn)
    133                         self.assertIn('密码强度不够,请重新输入密码!', text, ' 密码强度不够,请重新输入密码!')
    134                     elif item[0] != 'qwert1234!@#' and item[1] == item[2]:# >= 4
    135                         lowercase, uppercase, number, other = strhandle(item[1])
    136                         if (lowercase > 0 and uppercase > 0 and number > 0) or (
    137                                     lowercase > 0 and uppercase > 0 and other > 0) or (
    138                                     number > 0 and other > 0 and lowercase > 0) or (
    139                                     number > 0 and other > 0 and uppercase > 0):
    140                             text = menu.errorDialog(menu.closeBtn)
    141                             self.assertIn('旧密码输入错误!', text, '旧密码输入错误!')  # 新密码和确认码不同时断言提示信息
    142                     elif item[0] == 'qwert1234!@#$' and item[1] != item[2]:# and item[1] >= 4:
    143                         lowercase, uppercase, number, other = strhandle(item[1])
    144                         if (lowercase > 0 and uppercase > 0 and number > 0) or (
    145                                             lowercase > 0 and uppercase > 0 and other > 0) or (
    146                                             number > 0 and other > 0 and lowercase > 0) or (
    147                                             number > 0 and other > 0 and uppercase > 0):
    148                             text = menu.errorDialog(menu.closeBtn)
    149                             self.assertIn('两次输入的新密码不同!', text, ' 两次输入的新密码不同!')
    150                     else:
    151                         print('test value incorrect! please check it')
    152                 elif item[0] == '' or item[1] =='' or item[2] =='': # 输入项为空校验
    153                     text = menu.errorDialog(menu.closeBtn)
    154                     self.assertIn('该输入项的值不能为空!', text, ' 该输入项的值不能为空!')  # 所有密码均为空时断言提示信息
    155             else:
    156                 self.assertTrue(menu.isElementExist(menu.errMessage), 'error fram not exist, please check the test value or file bug')
    157 
    158 if __name__=='__main__':
    159     pass
     
    ​

    会员档案查询页面

     1 '''
      2 Code description:会员档案查询 page
      3 Create time:
      4 Developer:
      5 '''
      6 
      7 from retail.test_case.page_obj.base_page import queryData
      8 import time
      9 from selenium.webdriver.common.by import By
     10 import logging
     11 import sys
     12 from retail.test_case.page_obj.modifypw_page import PrimaryMenu, eleData
     13 from retail.test_case.models.log import Logger
     14 
     15 log = Logger(__name__, CmdLevel=logging.INFO, FileLevel=logging.INFO)
     16 
     17 
     18 class MemberQuery(PrimaryMenu):
     19     """
     20 
     21     """
     22     # 测试数据: 会员编码, 会员姓名, 手机号码
     23     valuesList = [queryData.readExcel(1, 1), int(queryData.readExcel(2, 1)), queryData.readExcel(3, 1)]
     24 
     25     # 会员档案下拉菜单
     26     memberMenu = (By.LINK_TEXT, eleData.readExcel(24, 3))
     27 
     28     # 会员查询页面的3个列表(查询条件,会员信息明细,积分变化明细)
     29     uiElements = (By.XPATH, eleData.readExcel(25, 3))
     30     # 会员类型
     31     memberTypeBtn = (By.ID, eleData.readExcel(26, 3))
     32     # 会员类型下拉选项
     33     memberTypeNum = [(By.XPATH, eleData.readExcel(27, 3)), (By.XPATH, eleData.readExcel(28, 3)),
     34                      (By.XPATH, eleData.readExcel(29, 3))]
     35 
     36     # 会员级别
     37     memberLevelBtn = (By.ID, eleData.readExcel(30, 3))
     38     # 会员级别下拉选项
     39     memberLevelNum = [(By.XPATH, eleData.readExcel(31, 3)), (By.XPATH, eleData.readExcel(32, 3)),
     40                       (By.XPATH, eleData.readExcel(33, 3)), (By.XPATH, eleData.readExcel(34, 3))]
     41 
     42     # 会员编号,会员姓名,手机号码
     43     memberNumNamePhone = [(By.ID, eleData.readExcel(35, 3)), (By.ID, eleData.readExcel(36, 3)),
     44                           (By.ID, eleData.readExcel(37, 3))]
     45     # 查询异常提示框
     46     qFailerr = (By.XPATH, eleData.readExcel(38, 3))  # 查询失败弹出的错误提示框
     47 
     48     confirmBtn = (By.XPATH, eleData.readExcel(39, 3))
     49 
     50     # 查询与重置
     51     queryResetBtn = [(By.ID, eleData.readExcel(40, 3)), (By.ID, eleData.readExcel(41, 3))]
     52 
     53     # 点击会员类型
     54     def selectMemberType(self):
     55         """
     56 
     57         :return:
     58         """
     59         try:
     60             self.findElement(*self.memberTypeBtn).click()
     61             self.driver.implicitly_wait(2)
     62         except Exception:
     63             log.logger.exception('selecting member type fail ')
     64             raise
     65         else:
     66             log.logger.info('---selecting member type ')
     67 
     68     # 点击会员级别
     69     def selectMemberLevel(self):
     70         """
     71 
     72         :return:
     73         """
     74         try:
     75             self.findElement(*self.memberLevelBtn).click()
     76             self.driver.implicitly_wait(2)
     77         except Exception:
     78             log.logger.exception('selecting member level fail ')
     79             raise
     80         else:
     81             log.logger.info('---selecting member level ')
     82 
     83     # 查找会员档案查询菜单
     84     def memberQueryMenu(self):
     85         """
     86 
     87         :return:
     88         """
     89         self.findElement(*self.menuList[1]).click()
     90         self.findElement(*self.memberMenu).click()
     91         time.sleep(4)
     92         log.logger.info('page [%s] :found the menu [%s] and [%s]' % (
     93             sys._getframe().f_code.co_name, self.menuList[1], self.memberMenu))
     94 
     95     # 会员类型/会员级别下拉选项
     96     def memberTypeLevelOption(self, *xpathList):
     97         """
     98 
     99         :param xpath_list:
    100         :return:
    101         """
    102         try:
    103             member_type_level = self.findElement(*xpathList)
    104             text = member_type_level.text
    105         except Exception:
    106             log.logger.exception('get element member type/level item text fail', exc_info=True)
    107             raise
    108         else:
    109             log.logger.info('get element [%s] member type/level item text [%s] fail' % (xpathList, text))
    110             return text, member_type_level
    111 
    112     # 点击查询和重置按钮
    113     def cQueryResetBtn(self, *queryResetBtn):
    114         """
    115 
    116         :param query_reset_btn:
    117         :return:
    118         """
    119         try:
    120             self.findElement(*queryResetBtn).click()
    121         except Exception:
    122             log.logger.exception('query/reset button not click', exc_info=True)
    123             raise
    124         else:
    125             log.logger.info('clicking query/reset button ')
    126 
    127     # 输入查询条件
    128     def iQueryCondition(self, numNamePhone, value):
    129         """
    130 
    131         :param numNamePhone:
    132         :param value:
    133         :return:
    134         """
    135         number_name_phone = self.findElement(*numNamePhone)
    136         try:
    137             number_name_phone.clear()
    138             number_name_phone.send_keys(value)
    139         except Exception:
    140             log.logger.exception('input value error', exc_info=True)
    141             raise
    142         else:
    143             log.logger.info('[%s] is typing value [%s] ' % (numNamePhone, value))
    144 
    145     # 获取条件输入框的内容
    146     def getInputboxValue(self, *memberNumNamePhone):
    147         """
    148 
    149         :param memberNumNamePhone:
    150         :return:
    151         """
    152         try:
    153             get_member_number_name_phone_text = self.findElement(*memberNumNamePhone)
    154             text = get_member_number_name_phone_text.get_attribute('value')
    155         except Exception:
    156             log.logger.exception('get value of element fail', exc_info=True)
    157             raise
    158         else:
    159             log.logger.info('get value [%s] of element [%s] success' % (memberNumNamePhone, text))
    160             return text
    161 
    162     # 重置功能的重写
    163     def reset(self):
    164         """
    165 
    166         :return:
    167         """
    168         try:
    169             self.findElement(*self.memberNumNamePhone[0]).clear()
    170             self.findElement(*self.memberNumNamePhone[1]).clear()
    171             self.findElement(*self.memberNumNamePhone[2]).clear()
    172         except Exception:
    173             log.logger.exception('reset fail', exc_info=True)
    174             raise
    175         else:
    176             log.logger.info('reset [%s]-[%s]-[%s] success' % (
    177                 self.memberNumNamePhone[0], self.memberNumNamePhone[1], self.memberNumNamePhone[2]))
    178 
    179 
    180 if __name__ == '__main__':
    181     pass

    加油吧,测试人!如果你需要提升规划,那就行动吧,在路上总比在起点观望的要好。未来的你肯定会感谢现在拼命的自己!

    物联沃分享整理
    物联沃-IOTWORD物联网 » 全面详细的Python Selenium自动化测试实战项目指南

    发表评论