Python3学习笔记之-错误、调式、测试(第二篇)

Python3学习笔记之-错误、调式、测试(第二篇)


一、调试

1.断言

程序避免不了就是出错,原始的解决方法就是用print()打印出来,但是这种方法不仅麻烦还会增加没用的代码,这个时候就出现了断言(assert),只要可以用print的地方就能够用断言来替代:

def foo(s):
    n = int(s)
    assert n != 0, 'n is zero!'
    return 10 / n

def main():
    foo('0')

assert的意思是,表达式n != 0应该是True,否则根据程序运行的逻辑,后面代码肯定会出错。

如果断言失败,assert语句本身就会抛出AssertionError:

$ python err.py
Traceback (most recent call last):
  ...
AssertionError: n is zero!

程序中如果到处充斥着assert,和print()相比也好不到哪去。不过,启动Python解释器时可以用-O参数来关闭assert

$ python -O err.py
Traceback (most recent call last):
  ...
ZeroDivisionError: division by zero

 注意:断言的开关“-O”是英文大写字母O,不是数字0。

关闭后,你可以把所有的assert语句当成pass来看。

2.logging

print()替换为logging是第3种方式,和assert比,logging不会抛出错误,而且可以输出到文件:

import logging

s = '0'
n = int(s)
logging.info('n = %d' % n)
print(10 / n)

logging.info()就可以输出一段文本。运行,发现除了ZeroDivisionError,没有任何信息。怎么回事?

别急,在import logging之后添加一行配置再试试:

import logging
logging.basicConfig(level=logging.INFO)

看到输出了:

$ python err.py
INFO:root:n = 0
Traceback (most recent call last):
  File "err.py", line 8, in <module>
    print(10 / n)
ZeroDivisionError: division by zero

这就是logging的好处,它允许你指定记录信息的级别,有debuginfowarningerror等几个级别,当我们指定level=INFO时,logging.debug就不起作用了。同理,指定level=WARNING后,debuginfo就不起作用了。这样一来,你可以放心地输出不同级别的信息,也不用删除,最后统一控制输出哪个级别的信息。

logging的另一个好处是通过简单的配置,一条语句可以同时输出到不同的地方,比如console和文件。

3.pdb

python的调试器pdb,让程序以单步方式运行,

python -m pdb hello.py

启动-m pdb后,输入(pdb)1可以查看代码,输入(pdb)n可以单步执行代码,输入(pdb)变量名,就可以查看变量,输入(pdb) q结束调试,

它确实可以让程序一步一步运行,然后寻找到哪一步出错,但是如果有几千行代码就太麻烦了。

4.pdb.set_trace()

这个方法也是用pdb,但是不需要单步执行,我们只需要import pdb,然后在一个可能出错的地方放一个pdb.set_trace(),就可以设置一个断点:

# err.py
import pdb

s = '0'
n = int(s)
pdb.set_trace() # 运行到这里会自动暂停
print(10 / n)

 运行代码,程序会自动在pdb.set_trace()暂停并进入pdb调试环境,可以用命令p查看变量,或者用命令c继续运行,但是效率也只能说略微提高一点。上面的方法基本上用不到,我们用到最方便快捷的那就是IDE,就是支持调试的编程工具,比如vs code,或者pycharm,但是程序编写久了,logging才会给你带来意想不到的惊喜。

二、单元测试

单元测试是针对程序模块的进行正确性检验的测试工作,测试保证了程序的健壮性,可以让你考虑代码的设计。

1.python测试相关库

  • unittest 内置库,模仿PyUnit写的,简洁易用,缺点是比较繁琐。
  • nose 测试发现,发现并运行测试。
  • pytest 写起来很方便,并且很多知名开源项目在用,推荐。
  • mock 替换掉网络调用或者 rpc 请求等

2.pytest进行单元测试

python内置了一个unittest,但是写起来稍微繁琐,比如都要写一个TestCase类,还得用 assertEqual, assertNotEqual等断言方法。 而使用pytest运行测试统一用assert语句就行,兼容unittest,目前很多知名开源项目如PyPy,Sentry也都在用。关于pytest的使用可以参考其官方文档,虽然有很多高级特性,但是掌握其中一小部分基本就够用了。

下面是py.test的基本用法,以常见的两种测试类型(验证返回值和抛出异常)为例:

def add(a, b):
    """return a + b

    Args:
        a (int): int
        b (int): int

    Returns:
        a + b

    Raises:
        AssertionError: if a or b is not integer

    """
    assert all([isinstance(a, int), isinstance(b, int)])
    return a + b


def test_add():
    assert add(1, 2) == 3
    assert isinstance(add(1, 2) , int)
    with pytest.raises(Exception):    # test exception
        add('1', 2)

这是个脑残示例,不过基本使用就是这么简单。真实场景下远远比这个复杂,甚至有时候构造测试的时间比写业务逻辑的时间还要长。但是再复杂的逻辑也是一点点功能堆积,如果可以确保每一部分都正确,整体上是不会出错的。单元测试同时也提醒我们,函数完成的功能尽可能单一,这样才利于测试。

下面几个是常用的pytest命令:

py.test test_mod.py   # run tests in module
py.test somepath      # run all tests below somepath
py.test -q test_file_name.py    # quite输出
py.test -s test_file_name.py    # -s参数可以打印测试代码中的输出,默认不打印,print没结果
py.test test_mod.py::test_func  # only run tests that match the "node ID",
py.test test_mod.py::TestClass::test_method  # run a single method in

3.测试驱动开发(TDD)的流程

错误:匆匆写代码->实现后print输出看结果->有逻辑或语法错误->修改->继续print输出看结果 循环往复。

采用TDD的流程如下:

TDD三项法则:

  1. 在编写失败的单元测试之前,不要编写任何产品代码
  2. 只要有一个单元测试失败了,就不再写测试代码;
  3. 产品代码能够让当前失败的单元测试成功通过即可,不要多写

三、文档测试

Python中的文档测试doctest非常之简单,就是对注释部分测试,举例:

#coding:UTF-8
import doctest
def ceshi(x):
    """#这是文档测试的内容
    >>> ceshi(2)
    1
    >>> ceshi(3)
    0
    """#End
    if x%2==0:
        return 1
    else:
        return 0
if __name__ == "__main__":    

    doctest.testmod(verbose=True)    

#doctest.testmod是测试模块,verbose默认是False,意思是出错才用提示;True,对错都有执行结果

 下面是运行结果:

Trying:
    ceshi(2)
Expecting:
    1
ok
Trying:
    ceshi(3)
Expecting:
    0
ok
1 items had no tests:
    __main__
1 items passed all tests:
   2 tests in __main__.ceshi
2 tests in 2 items.
2 passed and 0 failed. #显示两个测试都通过了
Test passed.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Python学习笔记》是由皮大庆编写的一本关于Python语言学习的教材。在这本书中,作者详细介绍了Python语言的基础知识、语法规则以及常用的编程技巧。 首先,作者简要介绍了Python语言的特点和优势。他提到,Python是一种易于学习和使用的编程语言,受到了广大程序员的喜爱。Python具有简洁、清晰的语法结构,使得代码可读性极高,同时也提供了丰富的库和模块,能够快速实现各种功能。 接着,作者详细讲解了Python的基本语法。他从变量、数据类型、运算符等基础知识开始,逐步介绍了条件语句、循环控制、函数、模块等高级概念。同时,作者通过大量的示例代码和实践案例,帮助读者加深对Python编程的理解和应用。 在书中,作者还特别强调了编写规范和良好的编程习惯。他从命名规范、注释风格、代码缩进等方面指导读者如何写出清晰、可读性强的Python代码。作者认为,良好的编程习惯对于提高代码质量和提高工作效率非常重要。 此外,作者还介绍了Python的常用库和模块。他提到了一些常用的库,如Numpy、Pandas、Matplotlib等。这些库在数据处理、科学计算、可视化等领域有广泛的应用,帮助读者更好地解决实际问题。 总的来说,《Python学习笔记》是一本非常实用和全面的Python学习教材。通过学习这本书,读者可以系统地学习和掌握Python编程的基础知识和高级应用技巧,为以后的编程学习和工作打下坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是小先生

知识是无价的,白嫖也可以的。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值