python|渣渣辉喊你玩贪玩改错啦!

综合编程 2018-02-13

前言

大家好,我系渣渣辉, 给大家推荐一款超好玩的游戏——贪玩改错。

【一】大怪出现 (异常处理)

一提到怪物,人们就会想到 bug ,可是这只是其中一类。其实还有两类:一个是用户输入错误,我们会提醒用户让他们检查;另一类就是完全无法预测的错误了,像python这种高级语言都贴心地内置了一套异常处理机制,比如:

try……except……else……语句

try-finally 语句

看一下可能出现小怪的模样:

示例(单个异常)

使用raise语句自己触发异常

所以啊,世上虽然有像我这么完美的玩家,却没有一个顺畅的成功之路。游戏能一次通关并正常运行的概率微乎其微。但我渣渣辉岂能败给这些小小的错误?!于是我集齐了一整套神器来修复bug,开始了打怪 调试 之路(就是我再 写一段代码去检查错 误)……

开始打怪!

【二】打怪从小开始(单元调试)

一屋不扫何以扫天下?打怪也要从小抓起、从 一个模块、一个函数或一个类 开始进行!

比如函数abs()吧,我们就写出几个测试用的例子:输入正数,期待返回值与输入相同;输入负数,期待返回值与输入相反;输入0,期待返回0;输入非数值类型,比如None、[]、{},期待抛出TypeError。 把上面的测试用例放到一个测试模块里,就是一个完整的单元测试 。那我用什么方法呢?

(1)Python单元测试必杀技之unittest

了解xUnit系列框架的小伙伴对这个肯定很熟悉,因为这就是其中一员。(可惜我没学过呜呜!

命令行接口、测试案例自动搜索、创建测试代码、构建测试套件方法等内容,需要的朋友可以参考下

①它主要包括:

1.测试脚手架(test fixture)——准备工作和扫尾工作.包括setUp()和tearDown().

2.测试案例(test case)——最小的测试单元.

3.测试套件(test suite)——测试案例的集合.

4.测试运行器(test runner)——测试执行的组件.

②自动击杀(测试案例自动搜索)

unittest支持简单的test discovery. 命令行传入discovery后,框架会自动在当前目录搜索要测试的案例并执行.搜索目录必须是包或者模块.基本使用如下:

 cd project_directory
python -m unittest discover

技能选择如下:

-v, –verbose 输出信息的详细级别;

-s, –start-directory directory 开始搜索目录 (默认为当前目录);

-p, –pattern pattern 匹配的文件名 (默认为test*.py);

-t, –top-level-directory directory 搜索的顶层目录 (默认为start directory)。

③创建测试代码

方式一: 创建子类继承unittest.TestCase

class WidgestTestCase(unittest.TestCase):
    def setup(self):
         pass
    def runTest(self):
          pass
     def tearDown(self):
          pass

方式二: 编写以test开头的方法

class WidgetTestCase(unittest.TestCase):
     def setUp(self):
         pass
    def test_xx1(self)
     def test_xx2(self)
     ...
     def test_xxN(self)
    def tearDown(self):
         pass

④构建测试套件

def suite():

suite = unittest.TestSuite()

suite.addTest(WidgetTestCase('test_default_size'))

suite.addTest(WidgetTestCase('test_resize'))

return suite

def suite():

tests = ['test_default_size', 'test_resize']

return unittest.TestSuite(map(WidgetTestCase, tests))

(2) Python单元测试必杀技之pytest

这个必杀技与python自带的unittest类似,但是比unittest使用起来更简单,打怪效率也更高。而且它能够支持简单的单元测试和复杂的功能测试;支持参数化;具有很多第三方插件,并且可以自定义扩展;方便的和持续集成工具集成。

听起来就好牛逼的样子是不是?实际上也真的很牛逼!

①安装

像安装python的其它软件一样,直接用 pip 安装。

 pip install -U pytest 
 py.test --version # 安装完成后,验证安装的版本

②实战

 # content of test_sample.py
def func(x):                     # 定义一个被测试函数func
      return x+1                 # 该函数将传递进来的参数加1后返回
def test_func():               # 再定义一个测试函数test_func用来对func进行测试
      assert func(3) == 5    #用断言语句assert来对结果进行验证

当打多个怪(需要编写多个测试样例)时,我们可以将其放到一个测试类当中:

 # content of test_class.py
    class TestClass:
      def test_one(self):
          x = "this"
          assert 'h' in x
       def test_two(self):
          x = "hello"
          assert hasattr(x, 'check')  

③如何召唤技能(如何编写pytest测试样例

通过上面2个实例,我们发现编写pytest测试样例非常简单,只需要按照下面的规则:

测试文件以test_开头(以_test结尾也可以);测试类以Test开头,并且不能带有 __init__ 方法;测试函数以test_开头;断言使用基本的assert即可。

④如何使用技能(如何执行pytest测试样例 )

方法很多种,上面第一个实例是直接执行py.test,第二个实例是传递了测试文件给py.test。其实py.test有好多种方法执行测试:

1. py.test                       # run all tests below current dir  
2. py.test test_mod.py   # run tests in module  
3. py.test somepath      # run all tests below somepath  
4. py.test -k stringexpr # only run tests with names that match the  
                                    # the "string expression", e.g. "MyClass and not method"  
                                    # will select TestMyClass.test_something  
                                    # but not TestMyClass.test_method_simple  
8. py.test test_mod.py::test_func # only run tests that match the "node ID",                                                                            # e.g "test_mod.py::test_func" will select                                                                            # only test_func in test_mod.py  

⑤所获成就(测试报告)

pytest可以方便的生成测试报告,即可以生成HTML的测试报告,也可以生成XML格式的测试报告用来与持续集成工具集成。

生成HTML格式报告: py.test --resultlog=path

生成XML格式的报告: py.test --junitxml=path

⑥游戏提示(获取帮助信息)

1. py.test --version       # shows where pytest was imported from  
2. py.test --fixtures       # show available builtin function arguments  
3. py.test -h | --help      # show help on command line and config file options  

⑦最佳作战环境

其实对于测试而言,特别是在持续集成环境中,我们的所有测试最好是在虚拟环境中。这样不同的虚拟环境中的测试不会相互干扰的。由于我们的实际工作中,在同一个Jekins中,运行了好多种不同项目册的测试,因此,各个测试项目运行在各自的虚拟环境中。

将pytest安装在虚拟环境中:

1、将当前目录创建为虚拟环境virtualenv .        # create a virtualenv directory in the current directory source bin/activate # on unix  
2、在虚拟环境中安装pytest:
pip install pytest  �

【三】全杀(调试)

(1)技能一:print

这一技能简单直接粗暴有效,就是正面刚,不服就把你打……印出来:

# error.py

def foo(s):

n = int(s)

print '>>> n = %d' % n

return 10 / n

def main():

foo('0')

main()

执行后在输出中查找打印的变量值就行。

由于这一技能过于残暴,所以用过场面一度混乱,会产生很多垃圾信息。

(2) 技能二:assert

这一技能不仅可替代print(凡是用print来辅助查看的地方,都可以用断言(assert)来替代),而且不会场面会整齐一些(因为启动Python解释器时可以用-O参数来关闭assert,关闭后,所有的assert语句都当成pass来看)。

 # error.py
def foo(s):
     n = int(s)
     assert n != 0, 'n is zero!' # 表达式n != 0应该是True,否则后面的代码就会出错。
     return 10 / n
 def main():
      foo('0')                # 如果断言失败,assert语句本身就会抛出AssertionError

(3) 技能三:logging(必杀技!!)

这一绝妙技能不仅不会抛出错误,而且可以输出到文件:

 # error.py
import logging
 logging.basicConfig(level=logging.INFO)
 s = '0'
n = int(s)
logging.info('n = %d' % n)
print 10 / n

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

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

(4) 技能四:pbd

启动Python的调试器pdb,让程序以单步方式运行,可以随时查看运行状态。然而,这种通过pdb在命令行调试的方法理论上是万能的,但实在是太麻烦了,如果有一千行代码,要运行到第999行得敲多少命令啊。还好,我们还有另一种调试方法——pdb.set_trace()

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

 # error.py
import pdb
 s = '0'
n = int(s)
 pdb.set_trace()
# 运行到这里会暂停并进入pdb调试环境,可以用命令p查看变量,或用命令c继续运行
print 10 / n

(5) 技能五:IDE

如果要比较爽地设置断点、单步执行,就需要一个支持调试功能的IDE。目前比较好的Python IDE有PyCharm。另外,eclipse加上pvdev插件也可以调试Python程序。

有请我的好兄弟浒天洛

探挽 改错 ,介四里没有挽过的船新版本,挤需体验三番钟,里造会干我一样,爱像借款游戏。

简书

责编内容by:简书 (源链)。感谢您的支持!

您可能感兴趣的

Python – Duty work – Conversion of any... I'm trying to make a program to convert a number in any base to another base of the user's choice. T...
python基础===monkeytype可以自动添加注释的模块!... monkeytype 一个可以自动添加注释的模块! 先要下载: pip install monkeytype 以官网的sample code为例 #moudle.pyde...
递归问题学习二之卡牌组合问题 问题: 给定17中卡牌,每种卡牌的数值为1-17的平方,给定一个攻击值,卡牌的数值代表卡牌的攻击值,达到这样的攻击值能有多少种组合方式 思路: 题目中的卡牌是可以重复使用的,这个问题是一个...
Using two lists to define a variable in python I have two lists that have a relationship with each other. List1 is descriptors and List2 is ranking...
Programming Best Practices For Data Science This post was originally published here The data science life cycle is generally comprise...