测试框架 Seldom

安装

参考 : https://pipenv.pypa.io/en/latest/
安装使用 pipenv 进行环境管理和版本管理

1
2
3
4
5
6
$ pip install pipenv
$ pipenv install --pypi-mirror https://mirrors.aliyun.com/pypi/simple/ --skip-lock
...
Installing dependencies from Pipfile.lock (c5e5dd)...
To activate this project's virtualenv, run pipenv shell.
Alternatively, run a command inside the virtualenv with pipenv run.

设置 pycharm 的运行环境
Preferences | Project: {project-name} | Python Interpreter, 设置 Python Interpreter 为刚刚安装的虚拟环境的目录
image.png

文件目录和规范

文件树

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.
├── Pipfile # 环境文件
├── README.md # Readme
├── __init__.py
├── assets # 资源文件
├── poppy # 框架方法定义
│   ├── api_url.py
│   ├── fake.py
│   ├── params.py
│   └── system
│   ├── __init__.py
│   ├── captcha.py
│   └── user_login.py
├── reports # 报告
├── run.py # 支持环境的运行
├── test.py # 测试运行
├── test.py.sample
└── tests # 测试文件
├── 1-base # 基础
│   ├── __init__.py
│   └── test_sign.py # 基础 - 验证签名
........

tests 文件命名规范

文件命名

文件名称参考 tests/1-base/test_sign.py
说明:

1
2
3
tests/
1-base/ # 1 可以约定执行顺序外并无其他用途
test_sign.py # 文件名需要以 test_ 作为前缀, 来作为自动化执行的遍历(框架约定)

class 命名

例如上面的 tests/1-base/test_sign.py , class 类名应当为 TestBaseSign
class 名称组合示例

1
2
3
4
tests/1-base/test_sign.py
TestBaseSign
Base : 文件夹名称的驼峰模式
Sign : 文件名称的驼峰模式(去除test)

方法命名

方法需要以 test_ 作为函数前缀

1
2
3
4
5
6
7
8
9
10
11
12
13
class TestBaseSign(seldom.TestCase):
"""
测试用例查询
"""
def test_secret(self):
"""
项目不使用签名也可以进行访问
"""

self.post(PySystem.authLogin, data={
"_py_secret": cache.get('_py_secret')
})
self.assertStatusCode(200)

编写请求

因为请求继承自 requests, 所以传递的参数遵循 requests 约定
Developer Interface — Requests 2.28.1 documentation

编写 http 请求

1
2
3
4
5
# get
self.get("http://httpbin.org/get", params=payload)

# post
self.get("http://httpbin.org/post", data=payload)

编写 request 请求

对于当前版本来讲, get 请求可能返回乱码, 所以可以用 requests 替代

1
2
3
4
5
6
7
def test_pc(self, _, url):
"""
测试 Pc
"""

resp = requests.get(Seldom.base_url + url))
self.assertTrue(resp.status_code, 200)

因为 requests 返回的内容和 seldom 框架不一致, 需要用 requests 提供的方法进行校验

1
2
3
4
5
6
7
8
9
10
11
>>> r = requests.get('https://api.github.com/user', auth=('user', 'pass'))
>>> r.status_code
200
>>> r.headers['content-type']
'application/json; charset=utf8'
>>> r.encoding
'utf-8'
>>> r.text
'{"type":"User"...'
>>> r.json()
{'private_gists': 419, 'total_private_repos': 77, ...}

运行

运行单个测试

虽然 seldom 继承了 unittest, 但是直接在 ide 中运行单元测试则会丢失 seldom 的使用便捷性, 所以不允许使用 ide 进行代码运行
复制 test.py.sample并重命名为 test.py, 可以调整 seldom.main 的参数来运行单个例子:
使用方法参考: 快速开始 | seldom文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
if __name__ == "__main__":
# 清理缓存
cache.clear()

# 设置 secret
cache.set({
'_device_id': '11223344',
'_device_type': 'webapp',
})

# 执行测试用例目录
seldom.main(
case="tests.1-base.test_sign.TestBaseSign",
base_url="http://poppy.duoli.com",
title="Poppy 接口测试",
tester="多厘",
language="zh-CN",
# debug=True,
description="基本的接口测试"
)

运行方式

1
$ python test.py

运行环境测试

在开发过程中, 我们不可避免的会对不同的环境进行完整测试, 这里用到了 seldom 的 平台化支持 | seldom文档
我们可以在注释中添加 [prod]或者 [dev, test]来区分运行环境

1
2
3
4
class TestSeoProdOther(seldom.TestCase):
"""
[prod]测试其他蜘蛛的访问
"""

运行

1
$ python run.py --env dev

断言

断言继承与 unittest, 这里做一个简单的说明

seldom.case(框架断言)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
assertAlertText
assertElement
assertInPath
assertInTitle
assertInUrl
assertJSON
断言接口返回的某部分数据
assertNotElement
assertNotText
assertPath
是基于 jmespath 实现的断言
assertSchema
assertStatusCode
assertText
assertTitle
assertUrl

unittest

方法 检查对象 引入版本
assertEqual(a,b) a == b
assertNotEqual(a,b) a != b
assertTrue(x) bool(x) is True
assertFalse(x) bool(x) is False
assertIs(a,b) a is b 3.1
assertIsNot(a,b) a is not b 3.1
assertIsNone(x) x is None 3.1
assertIsNotNone(x) x is not None 3.1
assertIn(a,b) a in b 3.1
assertNotIn(a,b) a not in b 3.1
assertIsInstance(a,b) isinstance(a, b) 3.2
assertNotIsInstance(a,b) not isinstance(a, b) 3.2
方法 用作比较 引入版本
assertRaises(exc,fun,*args,**kwds) fun(*args, **kwds) 引发了 exc
assertRaisesRegex(exc,r,fun,*args,**kwds) fun(*args, **kwds) 引发了 exc 并且消息可与正则表达式 r 相匹配 3.1
assertWarns(warn,fun,*args,**kwds) fun(*args, **kwds) 引发了 warn 3.2
assertWarnsRegex(warn,r,fun,*args,**kwds) fun(*args, **kwds) 引发了 warn 并且消息可与正则表达式 r 相匹配 3.2
assertLogs(logger,level) with 代码块在 logger 上使用了最小的 level 级别写入日志 3.4
assertNoLogs(logger,level) with 代码块没有在 3.10
方法 用作比较 引入版本
assertAlmostEqual(a,b) round(a-b, 7) == 0
assertNotAlmostEqual(a,b) round(a-b, 7) != 0
assertGreater(a,b) a > b 3.1
assertGreaterEqual(a,b) a >= b 3.1
assertLess(a,b) a < b 3.1
assertLessEqual(a,b) a <= b 3.1
assertRegex(s,r) r.search(s) 3.1
assertNotRegex(s,r) not r.search(s) 3.2
assertCountEqual(a,b) ab 具有同样数量的相同元素,无论其顺序如何。 3.2
方法 用作比较 引入版本
assertMultiLineEqual(a,b) 字符串 3.1
assertSequenceEqual(a,b) 序列 3.1
assertListEqual(a,b) 列表 3.1
assertTupleEqual(a,b) 元组 3.1
assertSetEqual(a,b) 集合 3.1
assertDictEqual(a,b) 字典 3.1

相关框架


语雀镜像 : 测试框架 Seldom ,点此 提问

作者

Duoli

发布于

2022-10-11

更新于

2022-12-08

许可协议

评论