Python+selenium自动化测试实战项目(全面,完整,详细)

本文详述了一个使用Python和selenium进行自动化测试的实战项目,包括项目环境、框架设计、目标和具体代码实现。项目采用unittest框架,运用Page Object设计模式,实现了测试用例的执行报告、日志、邮件通知和数据驱动等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

问:

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  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值