Welcome to pithy-test’s documentation!¶
介绍¶
该项目意在简化接口自动化测试,使测试同学可以专心于业务测试用例的编写 目前已实现如下功能:
- 一键生成测试项目
- http client封装
- thrift client封装
- 日期时间处理工具
- json处理工具
- 配置文件解析
安装&更新¶
在这一章节中,我们介绍一下如何安装pithy-test.
删除¶
>>> pip uninstall pithy-test
获取源码¶
>>> git clone https://github.com/yuyu1987/pithy-test.git
快速开始¶
生成测试项目¶
查看使用方法¶
>>> pithy-cli
Usage: pithy-cli [OPTIONS] COMMAND [ARGS]...
pithy-cli是一个接口测试项目生成脚手架,功能完善中
Options:
--version Show the version and exit.
--help Show this message and exit.
Commands:
init 生成接口测试项目 使用方法: $ pithy-cli init # 生成接口测试项目
生成测试项目¶
>>> pithy-cli init
请选择项目类型,输入api或者app: api
请输入项目名称,如pithy-api-test: pithy-api-test
开始创建pithy-api-test项目
开始渲染...
生成 api/.gitignore [√]
生成 api/apis/__init__.py [√]
生成 api/apis/pithy_api.py [√]
生成 api/cfg.yaml [√]
生成 api/db/__init__.py [√]
生成 api/db/pithy_db.py [√]
生成 api/README.MD [√]
生成 api/requirements.txt [√]
生成 api/test_suites/__init__.py [√]
生成 api/test_suites/test_login.py [√]
生成 api/utils/__init__.py [√]
生成成功,请使用编辑器打开该项目
Attention
app还未开发,暂时还不能生成
生成的项目结构¶
>>> tree pithy-api-test
pithy-api-test
├── README.MD
├── apis
│ ├── __init__.py
│ └── pithy_api.py
├── cfg.yaml
├── db
│ ├── __init__.py
│ └── pithy_db.py
├── requirements.txt
├── test_suites
│ ├── __init__.py
│ └── test_login.py
└── utils
└── __init__.py
4 directories, 10 files
HTTP API测试¶
这个地方对python requests进行了封装,在原api不变的基础上,把原先的语句调用方式,扩展成了函数定义,然后对输出进行了包装,下面对比一下两种写法的不同
import requests
from pithy import request
# 直接使用requets的api
data = {'key': 'value'}
requests.get('http://www.xxx.com', data=data)
# 使用封装后的request
@request(url='http://www.xxx.com')
def get(value):
data = {'key': value}
return {'data': data}
之所以这么做,是因为这样可以更突显出api,更容易参数化,对session以及响应结果更好的处理
参数读取的大致流程如下:

使用POST方法,传参方式为表单格式¶
from pithy import request
@request(url='http://httpbin.org/post', method='post')
def post(self, key1='value1'):
"""
post method
"""
data = {
'key1': key1
}
return dict(data=data)
# 使用
response = post('test').to_json() # 解析json字符,输出为字典
response = post('test').json # 解析json字符,输出为字典
response = post('test').to_content() # 输出为字符串
response = post('test').content # 输出为字符串
response = post('test').get_cookie() # 输出cookie对象
response = post('test').cookie # 输出cookie对象
# 结果取值, 假设此处response = {'a': 1, 'b': { 'c': [1, 2, 3, 4]}}
response = post('13111111111', '123abc').json
print response.b.c # 通过点号取值,结果为[1, 2, 3, 4]
print response('$.a') # 通过object path取值,结果为1
for i in response('$..c[@>3]'): # 通过object path取值,结果为选中c字典里大于3的元素
print i
使用POST方法,传参方式为JSON¶
from pithy import request
@request(url='http://httpbin.org/post', method='post')
def post(self, key1='value1'):
"""
post method
"""
data = {
'key1': key1
}
return dict(json=data)
GET,URL传参¶
from pithy import request
@request(url='http://httpbin.org//get')
def get(self, key1='value1', key2=None):
"""
get method
"""
if key2 is None:
key2 = ['value2', 'value3']
params = {
'key1': key1,
'key2': key2
}
return dict(params=params)
使用类的方式组织用接口¶
使用同一session,指定base_url
from pithy import request
class PithyAPP(object):
def __init__(self):
self.base_url = 'http://httpbin.org
@request(url='/get')
def get(self, key1='value1', key2=None):
"""
get method
"""
if key2 is None:
key2 = ['value2', 'value3']
params = {
'key1': key1,
'key2': key2
}
return dict(params=params)
@request(url='post', method='post')
def post(self, key1='value1'):
"""
post method
"""
data = {
'key1': key1
}
return dict(data=data)
@request(url='post', method='post')
def json(self, key1='value1'):
"""
post method
"""
data = {
'key1': key1
}
return dict(json=data)
@request(url='login', method='post')
def _login(username, password):
"""
登录api
注: 该方法只是示例,并不能运行,请结合自己的项目使用
"""
data = {
'username': username,
'password': password
}
return dict(data=data)
def login(username, password):
"""
登录方法
注: 该方法只是示例,并不能运行,请结合自己的项目使用
"""
req = self._login(username, password)
cookies = res.cookies # 响应cookies
headers = res.headers # 响应headers
self.session.headers.update(xxx=headers.get('xxx')) # 设置session里的headers,设置之后,所有的请求均会带上
self.session.cookies.set('xxx', cookies.get('xxx')) # 设置session里的cookies,设置之后,所有的请求均会带上
# 使用,此处两个接口使用同一request session请求
app = PithyAPP()
app.get('value1').to_json()
app.post('value1).to_json()
工具集¶
配置管理¶
读取项目根目录下,或者当前目录下的配置文件,默认文件名为 cfg.yaml
,可传入 file_name
改变,目前支持解析的配置文件类型有 .ini
、.yaml
、.cfg
、.conf
yaml解析¶
例如cfg.yaml配置文件内容如下:
db:
pithy_db:
host: 127.0.0.1
port: 3306
username: user
password: 111111
使用方法如下:
from pithy import config_manager
config = config_manager()
print(config.db)
print(config.db.pithy_db)
ini解析¶
例如cfg.ini配置文件内容如下:
[pithy_db]
host = 127.0.0.1
port = 5432
username = postgres
password = postgres
使用方法如下:
from pithy import config_manager
config = config_manager(file_name='cfg.ini')
print(config.db.pithy_db)
conf和cfg格式与ini使用方法一致
日期处理¶
取当前时间¶
from pithy import HumanDateTime
print(HumanDateTime())
解析时间戳¶
解析任何有效的时间戳:
from pithy import HumanDateTime
# 解析时间戳
print(repr(HumanDateTime(1490842267)))
print(HumanDateTime(1490842267000))
print(HumanDateTime(1490842267.11111))
print(HumanDateTime(1490842267111.01))
解析字符串格式日期¶
解析常见字符串格式日期或时间:
from pithy import HumanDateTime
# 解析字符串格式日期
print(HumanDateTime('2017-02-02'))
print(HumanDateTime('Thu Mar 30 14:21:20 2017'))
print(HumanDateTime(time.ctime()))
print(HumanDateTime('2017-3-3'))
print(HumanDateTime('3/3/2016'))
print(HumanDateTime('2017-02-02 00:00:00'))
解析datetime或date类型时间¶
from pithy import HumanDateTime
# 解析datetime或date类型时间
print(HumanDateTime(datetime(year=2018, month=11, day=30, hour=11)))
print(HumanDateTime(date(year=2018, month=11, day=30)))
增加减少时间¶
from pithy import HumanDateTime
# 增加减少时间
print(HumanDateTime('2017-02-02').add_day(1))
print(HumanDateTime('2017-02-02').sub_day(1))
print(HumanDateTime('2017-02-02').add_hour(1))
print(HumanDateTime('2017-02-02').sub_hour(1))
print(HumanDateTime('2017-02-02').add(days=1, hours=1, weeks=1, minutes=1, seconds=6))
print(HumanDateTime('2017-02-02').sub(days=1, hours=1, weeks=1, minutes=1, seconds=6))
转换为时间戳¶
把任何格式的时间类型转换为时间戳:
from pithy import HumanDateTime
# 转换为时间戳
print(HumanDateTime(1490842267.11111).timestamp_second)
print(HumanDateTime(1490842267.11111).timestamp_microsecond)
print(HumanDateTime('2017-02-02 12:12:12.1111').add_day(1).timestamp_microsecond)
print(HumanDateTime('2017-02-02 12:12:12 1111').add_day(1).timestamp_microsecond)
比较大小¶
比较任何两个日期类型数据的大小:
from pithy import HumanDateTime
# 比较大小
print(HumanDateTime('2017-02-02 12:12:12 1111') < HumanDateTime('2017-02-02 12:12:11 1111'))
print(HumanDateTime('2017-02-02 12:12:12 1111') < HumanDateTime('2017-02-02 12:13:11 1111'))
print(HumanDateTime('2017-02-02 12:12:12 1111') < '2017-02-02 12:11:11')
print(HumanDateTime('2017-02-02 12:12:12 1111') < '2017-02-02 12:13:11 1111')
print(HumanDateTime('2017-02-02 12:12:12 1111') == '2017-02-02 12:13:11 1111')
print(HumanDateTime('2017-02-02 12:12:12 1111') == '2017-02-02 12:13:12 1111')
print(HumanDateTime('2017-02-02 12:12:12 1111') <= '2017-02-02 12:13:11 1111')
print(HumanDateTime('2017-02-02 12:12:12 1111') >= '2017-02-02 12:13:11 1111')
print(HumanDateTime('2017-02-02 12:12:12 1111') != time.time())
print(HumanDateTime('2017-02-02 12:12:12 1111') <= time.time())
print(HumanDateTime('2017-02-02 12:12:12 1111') >= time.time())
# 约等于或者接近
print(HumanDateTime('2017-02-02 12:12:12 1111').approach('2017-02-02 12:12:11 1111'))
print(HumanDateTime('2017-02-02 12:12:12 1111').approach('2017-02-02 12:12:10 1111'))
print(HumanDateTime('2017-02-02 12:12:12 1111').approach('2017-02-02 12:12:10 1111', offset=2))
print(HumanDateTime('2017-02-02 12:12:12 1111').approach('2017-02-02 12:12:14 1111', offset=2))
调用datetime的方法和属性¶
from pithy import HumanDateTime
# 调用datetime的方法和属性
print(HumanDateTime('2017-02-02 12:12:12 1111').day)
print(HumanDateTime('2017-02-02 12:12:12 1111').year)
print(HumanDateTime('2017-02-02 12:12:12 1111').second)
print(HumanDateTime('2017-02-02 12:12:12 1111').date())
操作复杂JSON或字典¶
优化JSON字符串和字典的取值方式,输入为python字典或者json字符串,可以通过点号或者 object path 对结果取值
操作JSON的KEY¶
from pithy import JSONProcessor
dict_data = {'a': 1, 'b': {'a': [1, 2, 3, 4]}}
json_data = json.dumps(dict_data)
result = JSONProcessor(json_data)
print result.a # 结果:1
print result.b.a # 结果:[1, 2, 3, 4]
操作字典的KEY¶
from pithy import JSONProcessor
dict_data = {'a': 1, 'b': {'a': [1, 2, 3, 4]}}
result = JSONProcessor(dict_data)
print result.a # 1
print result.b.a # [1, 2, 3, 4]
object path取值¶
这里使用的object path的取值方式,详细语法见:http://objectpath.org/reference.html
from pithy import JSONProcessor
raw_dict = {
'key1':{
'key2':{
'key3': [1, 2, 3, 4, 5, 6, 7, 8]
}
}
}
jp = JSONProcessor(raw_dict)
for i in jp('$..key3[@>3]'):
print i
结果是:
4
5
6
7
8
其它用法¶
dict_1 = {'a': 'a'}
json_1 = '{"b": "b"}'
jp = JSONProcessor(dict_1, json_1, c='c')
print(jp)
输出为:
{
"a": "a",
"b": "b",
"c": "c"
}
美化JSON打印¶
该函数是格式化打印 JSON
或 字典
,并对JSON中的unicode或utf-8字符进行转换
使用方法如下:
from pithy import pretty_print
d = {
"args": {
"name": "鱼鱼"
},
"headers": {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Accept-Encoding": "gzip, deflate, sdch",
"Accept-Language": "zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4",
"Connection": "close",
"Cookie": "_gauges_unique_day=1; _gauges_unique_month=1; _gauges_unique_year=1; _gauges_unique=1",
"Dnt": "1",
"Host": "httpbin.org",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
},
"origin": "157.119.234.165",
"url": "http://httpbin.org/get"
}
print(d)
print('\n\n)
pretty_print(d) # 该处也可以传入JSON字符串
输出结果为:
{'origin': '157.119.234.165', 'headers': {'Dnt': '1', 'Connection': 'close', 'Accept-Language': 'zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4', 'Accept-Encoding': 'gzip, deflate, sdch', 'Cookie': '_gauges_unique_day=1; _gauges_unique_month=1; _gauges_unique_year=1; _gauges_unique=1', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36', 'Host': 'httpbin.org', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Upgrade-Insecure-Requests': '1'}, 'args': {'name': '\xe9\xb1\xbc\xe9\xb1\xbc'}, 'url': 'http://httpbin.org/get'}
{
"args": {
"name": "鱼鱼"
},
"headers": {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Accept-Encoding": "gzip, deflate, sdch",
"Accept-Language": "zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4",
"Connection": "close",
"Cookie": "_gauges_unique_day=1; _gauges_unique_month=1; _gauges_unique_year=1; _gauges_unique=1",
"Dnt": "1",
"Host": "httpbin.org",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
},
"origin": "157.119.234.165",
"url": "http://httpbin.org/get"
}