1、行为驱动环境搭建:
安装:
|
1
2
3
|
pip install behavepip install pyhamcrest |
我们需要新建features包,在该包下要包含至少一个.feature文件和steps包,steps下包含对应执行的测试用例.py文件,场景描述文件写在.feature文件里
目录结构:

1)新建项目:feature_test
2)新建包:features
3)在features包中新建文件:register.feature ,写入场景描述:
# register.feature Feature: Register User As a developer This is my frist BDD project
Scenario: register_test # Given open register website When I open the register website Then I except that the title is "注册" # Scenario: input user_info # Then I set with useremail "nan@163.com" # And I set with username "nan" # And I set with password "111111" # And I set with code "tests" # And I click with register_button # Then I except that text "验证码错误"
4)在features包中新建environment.py环境:
from selenium import webdriver
def before_all(context):
context.driver = webdriver.Chrome()
def after_all(context):
context.driver.close()
5)在features包中新建steps包
6)在steps包下新建文件:register_user.py:
from behave import *
use_step_matcher(‘re‘) # 正则匹配
@when(‘I open the register website‘)
def step_register(context):
context.driver.get("http://www.5itest.cn/register")
@then(‘I except that the title is "([^"]*)"‘) # 匹配除"外的所有字符,0个或多个
def step_register1(context,title_name):
title = context.driver.title # 获取网页的title
assert title_name in title # assert断言
注意:BDD运行方式,是在终端,进入项目中,执行:behave ,本项目执行如下

运行结果:

logging模块是Python内置的标准模块,主要用于输出运行日志,可以设置输出日志的等级、日志保存路径、日志文件回滚等;相比print,具备如下优点:
import logging
import sys
# 获取logger实例,如果参数为空则返回root logger
logger = logging.getLogger("AppName")
# 指定logger输出格式
formatter = logging.Formatter(‘%(asctime)s %(levelname)-8s: %(message)s‘)
# 文件日志
file_handler = logging.FileHandler("test.log")
file_handler.setFormatter(formatter) # 可以通过setFormatter指定输出格式
# 控制台日志
console_handler = logging.StreamHandler(sys.stdout)
console_handler.formatter = formatter # 也可以直接给formatter赋值
# 为logger添加的日志处理器
logger.addHandler(file_handler)
logger.addHandler(console_handler)
# 指定日志的最低输出级别,默认为WARN级别
logger.setLevel(logging.INFO)
# 输出不同级别的log
logger.debug(‘this is debug info‘)
logger.info(‘this is information‘)
logger.warn(‘this is warning message‘)
logger.error(‘this is error message‘)
logger.fatal(‘this is fatal message, it is same as logger.critical‘)
logger.critical(‘this is critical message‘)
# 2016-10-08 21:59:19,493 INFO : this is information
# 2016-10-08 21:59:19,493 WARNING : this is warning message
# 2016-10-08 21:59:19,493 ERROR : this is error message
# 2016-10-08 21:59:19,493 CRITICAL: this is fatal message, it is same as logger.critical
# 2016-10-08 21:59:19,493 CRITICAL: this is critical message
# 移除一些日志处理器
logger.removeHandler(file_handler)
格式化输出日志:
# 格式化输出
service_name = "Booking"
logger.error(‘%s service is down!‘ % service_name) # 使用python自带的字符串格式化,不推荐
logger.error(‘%s service is down!‘, service_name) # 使用logger的格式化,推荐
logger.error(‘%s service is %s!‘, service_name, ‘down‘) # 多参数格式化
logger.error(‘{} service is {}‘.format(service_name, ‘down‘)) # 使用format函数,推荐
# 2016-10-08 21:59:19,493 ERROR : Booking service is down!
logging.basicConfig函数各参数: filename:指定日志文件名; filemode:和file函数意义相同,指定日志文件的打开模式,‘w‘或者‘a‘; format:指定输出的格式和内容,format可以输出很多有用的信息, 参数:作用 %(levelno)s:打印日志级别的数值 %(levelname)s:打印日志级别的名称 %(pathname)s:打印当前执行程序的路径,其实就是sys.argv[0] %(filename)s:打印当前执行程序名 %(funcName)s:打印日志的当前函数 %(lineno)d:打印日志的当前行号 %(asctime)s:打印日志的时间 %(thread)d:打印线程ID %(threadName)s:打印线程名称 %(process)d:打印进程ID %(message)s:打印日志信息 datefmt:指定时间格式,同time.strftime(); level:设置日志级别,默认为logging.WARNNING; stream:指定将日志的输出流,可以指定输出到sys.stderr,sys.stdout或者文件,默认输出到sys.stderr,当stream和filename同时指定时,stream被忽略;
# StreamHandler:logging.StreamHandler;日志输出到流,可以是sys.stderr,sys.stdout或者文件 # FileHandler:logging.FileHandler;日志输出到文件 # BaseRotatingHandler:logging.handlers.BaseRotatingHandler;基本的日志回滚方式 # RotatingHandler:logging.handlers.RotatingHandler;日志回滚方式,支持日志文件最大数量和日志文件回滚 # TimeRotatingHandler:logging.handlers.TimeRotatingHandler;日志回滚方式,在一定时间区域内回滚日志文件 # SocketHandler:logging.handlers.SocketHandler;远程输出日志到TCP/IP sockets # DatagramHandler:logging.handlers.DatagramHandler;远程输出日志到UDP sockets # SMTPHandler:logging.handlers.SMTPHandler;远程输出日志到邮件地址 # SysLogHandler: logging.handlers.SysLogHandler;日志输出到syslog # NTEventLogHandler: logging.handlers.NTEventLogHandler;远程输出日志到Windows NT/2000/XP的事件日志 # MemoryHandler:logging.handlers.MemoryHandler;日志输出到内存中的指定buffer # HTTPHandler:logging.handlers.HTTPHandler;通过"GET"或者"POST"远程输出到HTTP服务器
设置消息等级
# FATAL:致命错误 # CRITICAL:特别糟糕的事情,如内存耗尽、磁盘空间为空,一般很少使用 # ERROR:发生错误时,如IO操作失败或者连接问题 # WARNING:发生很重要的事件,但是并不是错误时,如用户登录密码错误 # INFO:处理请求或者状态变化等日常事务 # DEBUG:调试过程中使用DEBUG等级,如算法中每个循环的中间状态
当你使用logging模块记录异常信息时,不需要传入该异常对象,只要你直接调用logger.error() 或者 logger.exception()就可以将当前异常记录下来。
# 记录异常信息
try:
1 / 0
except:
# 等同于error级别,但是会额外记录当前抛出的异常堆栈信息
logger.exception(‘this is an exception message‘)
# 2016-10-08 21:59:19,493 ERROR : this is an exception message
# Traceback (most recent call last):
# File "D:/Git/py_labs/demo/use_logging.py", line 45, in
# 1 / 0
# ZeroDivisionError: integer division or modulo by zero
logging的配置大致有下面几种方式。
logging.config.fileConfig(filepath)
demo:日志模块应用
info级别以上内容会记入指定日志文件中
import logging
import os
import datetime
class UserLog(object):
def __init__(self):
self.logger1 = logging.getLogger(__name__) # 生成log对象
# 以下三行代码为清空上次创建log文件
logging.Logger.manager.loggerDict.pop(__name__) # 清空当前文件存于loggerDict的日志实例。(logging 模块为了保证同一个名称引用同一个日志实例,所以就把所有的日志实例全部存在了一个 loggerDict 的字典里,要释放某实例则需清除)
self.logger1.handlers=[] # 将handers清空
self.logger1.removeHandler(self.logger1.handlers) # 移除当前文件的logging相关配置
if not self.logger1.handlers: # 如果logger.handlers列表为空,则新添加,否则表示文件存在,可以直接去写日志
self.logger1.setLevel(logging.DEBUG)
#控制台输出日志
#consle = logging.StreamHandler()
#logger.addHandler(consle)
#文件名字
log_dir = os.path.dirname(os.path.abspath(__file__))
log_file = datetime.datetime.now().strftime("%Y-%m-%d") + ".log"
log_name = os.path.join(log_dir,"logs",log_file) # 日志文件名
#文件输出日志
self.file_handle = logging.FileHandler(log_name,‘a‘,encoding=‘utf-8‘)
self.file_handle.setLevel(logging.INFO)
formatter = logging.Formatter(‘%(asctime)s %(filename)s--> %(funcName)s %(levelno)s: %(levelname)s ----->%(message)s‘)
self.file_handle.setFormatter(formatter)
self.logger1.addHandler(self.file_handle)
def get_log(self):
return self.logger1
def close_handle(self):
self.logger1.removeHandler(self.file_handle)
self.file_handle.close()
# if __name__ == ‘__main__‘:
# user = UserLog()
# log = user.get_log()
# log.debug(‘test‘)
# user.close_handle()
"""
logging.Logger.manager.loggerDict.pop(__name__) self.logger1.handlers=[] self.logger1.removeHandler(self.logger1.handlers)
"""
解析:logging 模块为了保证同一个名称引用同一个日志实例,所以就把所有的日志实例全部存 在了一个 loggerDict 的字典里,。除非程序退出, 否则创建的日志实例引用是不会释放的, 日志实例里的 handlers 也不会释放.所以需要做以上操作处理。
在测试用例中操作:
# 1)setUpClass
@classmethod
def setUpClass(cls):
cls.log = UserLog()
cls.logger = cls.log.get_log()
cls.driver = webdriver.Chrome()
cls.driver.get(‘http://www.5itest.cn/register‘)
cls.driver.maximize_window()
cls.file_name = setting.code_path
cls.login = RegisterBusiness(cls.driver)
# 2)setUp
def setUp(self):
self.driver.refresh()
self.logger.info("this is chrome_tset")
# 3)tearDownClass
@classmethod
def tearDownClass(cls):
cls.log.close_handle()
cls.driver.close()
执行结果:

1、Jenkins 环境搭建,参考:https://www.cnblogs.com/Eric15/p/9834120.html
2、新建任务
Jenkins安装及配置好环境后,我们到Jenkins安装目录下执行命令:jenki.exe start ,启动服务器
浏览器访问:127.0.0.1:8080 , 进入服务器(需账号密码)
1)新建我们的第一个任务

2)命名并选择‘构建一个自由风格的软件项目’

3)进入下一步后,暂时只需要进行下面简单配置操作:
源码管理 → 先选无
构建 → 选择:执行Windows批处理命令
在命令里配置执行程序:python G:\Python\python_selenium\case\first_case.py
保存
执行 ‘立即构建’,之后可点击 ‘控制台输出’查看运行结果
跳出界面 → 
因本项目是在虚拟环境下配置的,故在构建时,python执行文件应该选择虚拟环境中的python执行文件:

3、Jenkins邮件通知


Selenium3与Python3实战 Web自动化测试框架(四)
原文:https://www.cnblogs.com/fujunjie/p/13160690.html