Python中的assert用法
本文转载自Python中不尽如人意的断言Assertion,如有侵权,立马删除!
使用assert
断言是学习Python一个非常好的习惯,Python assert 断言 语句格式及用法很简单;在没完善一个程序之前,我们不知道程序在哪里会出错,与其让它在运行时崩溃,不如在出现错误条件时就崩溃,这时候就需要assert断言的帮助;本文主要是将assert断言的基础知识。
Python assert 断言的作用
Python assert 断言是声明其布尔值必须为真的判定,如果发生异常就说明表达式为假。可以理解 assert断言语句为raise-if-not,用来测试表达式,其返回值为假,就会触发异常。
assert 断言语句的语法格式
assert Python怎么用?
expression assert 表达式
下面做一些assert用法的语句供参考:
assert 1==1
assert 2+2 == 2*2
assert len(['my boy', 12]) < 10
assert range(4) == [0,1,2,3]
如何为assert断言语句添加异常参数
assert的异常参数,其实就是在断言表达式后添加字符串信息,用来解释断言并更好的知道是哪里出了问题。格式如下:
assert expression[,arguments]
assert 表达式[,参数]
assert len(lists) >= 5, '列表元素个数小于5'
assert 2 == 1, '2不等于1'
Python assert 为何不尽如人意
Python中的断言用起来非常简单,你可以在assert后面跟上人意判断条件,如果断言失败则会抛出异常。
assert 1+1 == 2
assert isinstance('Hello', str)
assert isinstance('Hello', int)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError
其实assert
看上去不错,然而用起来并不友好;就比如有人告诉你程序错了,但是不告诉哪里错了;很多时候这样的assert
还不如不写;直接抛一个异常会更好一些。
改进方案 #1
s = 'nothin is impossible.'
key = 'nothing'
assert key in s, "key: '{}' is not in Target: '{}'".format(key, s)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError: key: 'nothing' is not int Target: 'nothin is impossible.'
看上去还行,但是其实很是有点不友好;假如你是一名测试员,有成千上万的测试案例需要做断言做验证,这样的做法就不适用了。
改进方案 #2
不管你是做测试还是开发的,想必听过不少测试框架;
py.test
py.test
是一个轻量级的测试框架,所以它压根就没写自己的断言系统,但是它对Python自带的断言做了强化处理,如果断言失败,那么框架本身会尽可能多地提供断言失败的原因。那么也就意味着,用py.test
实现测试,你一行代码都不用改。
import pytest
def test_case():
expected = 'Hello'
actual = 'hello'
assert expected == actual
if __name__ == '__main__':
pytest.main()
执行结果如下:
============================= test session starts =============================
platform win32 -- Python 3.7.1, pytest-4.4.1, py-1.8.0, pluggy-0.9.0
rootdir: E:\Python5\newmallpro\TestAPI
collected 0 items / 1 errors
=================================== ERRORS ====================================
________________________ ERROR collecting test_one.py _________________________
ImportError while importing test module 'E:\Python5\newmallpro\TestAPI\test_one.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
test_one.py:10: in <module>
import requests
E ModuleNotFoundError: No module named 'requests'
!!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!
=========================== 1 error in 0.14 seconds ===========================
unittest(单元测试)
Python自带的unittest
单元测试框架就有了自己的断言方法self.assertXXX()
,而且不推荐使用assert XXX
语句。
import unittest
class TestStringMethods(unittest.TestCase):
def test_upper(self):
self.assertEqual('foo'.upper(), 'FoO')
if __name__ == '__main__':
unittest.main()
执行结果如下:
FoO != FOO
Expected :FOO
Actual :FoO
<Click to see difference>
Traceback (most recent call last):
File "D:\appinstallation\pycharminstall\PyCharm 2018.3.1\helpers\pycharm\teamcity\diff_tools.py", line 32, in _patched_equals
old(self, first, second, msg)
File "D:\appinstallation\pythonInstall\lib\unittest\case.py", line 839, in assertEqual
assertion_func(first, second, msg=msg)
File "D:\appinstallation\pythonInstall\lib\unittest\case.py", line 1220, in assertMultiLineEqual
self.fail(self._formatMessage(msg, standardMsg))
File "D:\appinstallation\pythonInstall\lib\unittest\case.py", line 680, in fail
raise self.failureException(msg)
AssertionError: 'FOO' != 'FoO'
ptest
ptest
中的断言可读性很好,而且智能提示也很方便你通过IDE轻松完成各种断言语句。感谢Karl大神写了这个一个测试框架。
from ptest.decorator import *
from ptest.assertion import *
@TestClass()
class TestCases:
@Test()
def test1(self):
actual = 'foo'
expected = 'bar'
assert_that(expected).is_equal_to(actual)
if __name__ == '__main__':
TestCases().test1()
执行结果如下:
AssertionError: Unexpectedly that the str <bar> is not equal to str <foo>.
改进方案 #3
很多人对Python中的断言表示不满足,所以大家都争相发明自己的assert包。在这里我强烈推荐assertpy
这个包,
它异常强大而且好评如潮。
pip install assertpy
代码示例:
from assertpy import assert_that
def test_something():
assert_that(1 + 2).is_equal_to(3)
assert_that('foobar').is_length(6).starts_with('foo').ends_with('bar')
assert_that(['a', 'b', 'c']).contains('a').does_not_contain('x')
assert_that('a').is_length(4)
if __name__ == '__main__':
test_something()
执行结果如下:
AssertionError: Expected <a> to be of length <4>, but was <1>.
从他的github 主页文档上你会发现它支持了几乎你能想到的所有所有测试场景,包括但不限于一下列表:
- Strings
- Numbers
- Lists
- Tuples
- Dicts
- Sets
- Booleans
- Dates
- Fiels
- Objects
而且它的断言信息简洁明了,不多不少。
Expected <foo> to be of length <4>, but was <3>.
Expected <foo> to be empty string, but was not.
Expected <False>, but was not.
Expected <foo> to contain only digits, but did not.
Expected <123> to contain only alphabetic chars, but did not.
Expected <foo> to contain only uppercase chars, but did not.
Expected <FOO> to contain only lowercase chars, but did not.
Expected <foo> to be equal to <bar>, but was not.
Expected <foo> to be not equal to <foo>, but was.
Expected <foo> to be case-insensitive equal to <BAR>, but was not.
总结
断言在软件中有非常重要的作用,写的好可以让你的系统更稳定,也可以让你有更多真正面对对象的时间,而不是在调试代码。
Python中默认的断言语句其实还有一个作用,如果你写了一个类型相关的断言,IDE会把这个对象当成这种类型,这时候智能提示就有如神助。
要不要把内置的断言语句换成可读性更好功能更强大的第三方断言,完全取决于实际情况。比如你真的需要验证某个东西并且很关心验证结果,那么必须不能用简单的assert;如果你只是担心某个点可能有坑或者让IDE认识某个对象,用内置的assert既简单又方便。
本文转载自Python中不尽如人意的断言Assertion,如有侵权,立马删除!