Coding Python

无尽


  • Home

  • Archives

测试代码单元测试unittest

Posted on 2020-01-16 | In Python进阶 |

一、单元测试和集成测试

  1. 集成测试
    你回想一下,你刚有一台属于自己的电脑的时候,你是如何确定它能够使用的呢?
    你会接上电源,然后按一下主机的开关按钮,然后会听到风扇开始转动的声音,这时候你的双眼会死死的盯住电脑的显示器,你的期望结果是:这个显示器等会会亮起来,然后有一个开机动画。
    过了一会之后,你的显示器亮了起来,和你想的一样,可以玩耍了。
    在这里,你按住开关按钮是测试的步骤,你死死盯住电脑期望它亮起来是你的测试断言。
    再想一下,如果结果和你的断言不符呢?
    也就是说:挖槽!居然显示器一直不亮,那还玩个毛线啊?
    这时候你可能会想:是不是主机里的电源没接好呢?是不是 CPU 烧坏了?是不是内存条没插好?是不是主板秀逗了?
    其实你的这一系列的测试动作,叫做集成测试,它主要是测试各个组件是否相互协作成功,也就是说,有时候你写的代码中,某个模块是可以运行的,但是和别的代码一起使用的时候,可能就会出现问题了。

集成测试一般是在单元测试之后的。

  1. 单元测试
    单元测试就是测试更小范围的东西,如一行代码、一个函数、一个class 、 一个模块等
    unittest 测试库 再举一个简单的例子
    结果正确的情况: 不正确的情况 测试 failed ,测试结果 与期望结果 不同,修改代码。
    用命令行执行测试用例 以上是为了方便理解,实际测试中不会直接在源代码中执行测试代码,需要额外创建一个 test.py 进行单元测试 现在要测试calc模块中的__init__.py 中的 add 方法
    在test.py 中写下测试代码如下 ,将测试代码与业务代码分离: 测试通过结果如下
    将 add 方法写错,测试不通过如下: 从测试结果看出,5+6 想要的结果是11,而 add 方法是乘积 30,说明方法存在问题。
    这里只用到了 assertEqual,判断是否与期望的结果相同,unittest 还封闭了其它方法,常用方法如下: 本篇只是对单元测试有个简单的认识,更高级的用法在下一篇继续吹。

二、unittest中常用的操作

接上文,面对项目中有多个方法函数需要测试的情况

这时要测试 add 和 minus 方法,同理是这样测试的

测试通过

系列测试 TextTestRunner

可以看到,这种方式不能改变测试的顺序,不太灵活,下面采用另外外测试方法
不是单个单个的测试,而是进行一个系列的测试,
首先在测试类中添加所有要测试的函数

这次主要区别是又新建一个测试文件 test_suite.py,其中导入 unittest 和 上一步写的测试类 TestCalc,接着获取TestSuite 对象,在 tests 列表中设定测试顺序,添加进测试对象,获取 TextTestRunner 对象,然后就可以 run 运行了。具体一步一步仔细看代码

测试通过:

跳过测试 skip

部分方法不用测试时可以选择跳过 skip
这里用装饰器调用 unittest 中的skip

从结果看到,成功跳过除法测试。

经过实践这里运行 test.py 才能输出

Skipped: 跳过 除法运算 测试!!!!

如果运行 test_suite.py 则只剩这个输出

unittest两个重要方法

setUp: 在执行测试前的准备动作
tearDown: 在执行测试后的操作

可以在测试类中添加这两个方法

从测试结果看到,除跳过 skip 没有调用外,每个测试均调用了测试前 setUp 和测试后 tearDown 方法,

对于异常的测试,比如我们这里除数不能为 0 ,那么当我们可以写一个测试方法,当这个方法触发 ZeroDivisionError 才能通过:

因此添加了以上代码,触发了 ZeroDivisionError ,才能通过

把参数 b 改成非 0 的其它数字后的输出

大概理解为:没有抛出异常,所以测试没有通过。

如何在python中使用日志logging

Posted on 2020-01-16 | In Python进阶 |

日志的作用

  1. 它可以记录你写的代码的情况,比如用户在什么时候做了什么操作,导致了什么样的错误,在哪一行代码出错了…

  2. 可以清晰的了解你的程序的执行流程。

  3. 可以通过日志来分析,你的代码哪里可以优化得更好一点。

  4. 日志和直接 print 的区别在于,日志可以存储,你可以将记录下来的日志存储到指定的目录,根据时间区分文件,下次就可以直接到指定位置查看。

  5. 日志可以配置,你可以让日志以你喜欢的格式输出,可以指定它的存储位置等。

python内置日志模块 logging 介绍

一般情况下,logging 的级别有这么几种:

  1. Debug (调试信息)

  2. Info (日志信息)

  3. Warning (警告信息)

  4. Error (错误信息)

  5. Critical (严重危险信息)

下面分别来操作一下

可以看到,调试信息与日志信息不会输出,其它三个会输出,输不输出这都可以设置的
默认输出格式如下:log级别:log用户:信息
WARNING:root:警告信息
ERROR:root:错误信息
CRITICAL:root:严重危险信息
默认的 log用户为 root, 可以修改如下 :

设置logging

  1. 设置要记录的日志级别为 Debug 级 debug级的信息成功输出
  2. 设置输出格式

    process : 进程

levelname: 日志级别名称

message: 日志信息

asctime: 时间

用 format 或者 f-string 对输出结果再次加内容格式化输出

  • format
  • f-string

用logging 捕获异常

结合try…except 捕获异常信息

灵活用在需要的地方

将日志存储为文件

在设置中增加了一条
再次运行没有适时输出,但生成了一个文件

同样可以对输出文件的内容进行格式化

还可以单独建立配置文件,在项目中直接引用以统一所有模块的日志风格
配置文件模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[loggers] 
keys=root,simpleExample

[handlers]
keys=consoleHandler

[formatters]
keys=simpleFormatter

[logger_root]
level=DEBUG
handlers=consoleHandler

[logger_simpleExample]
level=DEBUG
handlers=consoleHandler
qualname=simpleExample
propagate=0

[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)

[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=

运行结果:

电子书或者Python文档如何制作供远程访问

Posted on 2020-01-13 | In Python进阶 |

本文主要讲解的是: 用 md 文件生成 html 电子书,再将html 电子书push 到 github,以供随时访问
本地 –> 在线,更方便访问
sphinx 可以将 Docstring 生成 HTML 文档,直接用浏览器本地打开 index.html 可以看文档,现在看更高级的运用,写成在线的电子书的形式,随时随地可看怎么操作呢?
比如这样的电子书爽吧!

这里演示使用read the doc 来创建免费开源的,它可以使用 Github webhook,也就是说,当生成的文档或者电子书托管到 Github 后,就可以和 read the doc 进行关联,这样每次更新 push 到 Github,read the doc 也会跟着一起更新,非常方便。
下面看具体使用步骤:

  1. sphinx-quickstart 命令创建配置文件 自动创建好这些文件
  2. 进入 source 目录,创建 md 文件
    让 sphinx 支持 markdown ,需要安装 recommonmark 同样要修改配置文件 conf.py 如下添加代码
  3. 安装 rtd 主题
    1
    pip install sphinx_rtd_theme

修改 conf.py ,将 theme 主题替换为rtd

  1. 在 index.rst 中添加文件索引
    即将 md 文件加入进来

这里特别需要注意,md文件前只能打三个空格

否则会报错如下

  1. make html生成 html
    一切准备就绪,输入 *make html * 更好的电子书就制作完成,如下图 打开 index.html 文件查看电子书如下:

一本电子书就制作完成了,下面将其托管到 github 上

  1. 将其托管到 github 上
    首先在 Github 创建一个仓库 一系列的git 命令如下
    1
    2
    3
    4
    5
    git init
    git add .
    git commit -m "add docs"
    git remote add origin https://github.com/lstyxr/python-ReadTheDoc.git
    git push origin master

强制覆盖提交就不要了吧,这个会造成原来的提交全部消失清空,不可恢复
最后 push 可能会出问题,采用强行提交

1
git push origin master -f //强行让本地分支覆盖远程分支

成功提交,但github仓库以往的信息全部清空了,下次还是先同步再提交吧,具体怎么同步是先 git pull 还是其它的命令还要再研究下

  1. git pull origin master –allow-unrelated-histories //把远程仓库和本地同步,消除差异
  2. 重新add和commit相应文件
  3. git push origin master
  4. 此时就能够上传成功了
  1. 注册 https://readthedocs.org/ 账号
    然后 import 项目 点选 手动导入 , 把 github 地址填入,注意这里的项目名称是乎要和git 仓库名称一样才行 然后它就会开始去 hook: 暂时还没弄清楚为什么会构建失败!!!

将你的Docstring生成在线HTML文档

Posted on 2020-01-09 | In Python进阶 |

当写完程序,加上了 Docstring 后,可以将 Docstring 生成在线HTML文档,以直接访问网页方式了解项目功能情况。
sphinx 命令工具可以很方便地将代码中的解释直接生成网页。
其具体操作如下:

安装 sphinx

1
pip install -U sphinx

如果安不上,用以下命令试试

1
easy_install -U sphinx

安装完成后就可以在当前项目中使用 sphinx 了

具体使用步骤

这里用自建的 calc 模块为例

  1. 新建 docs 文件夹
    在当前项目下新建 docs 文件夹,用于存放生成的文档
    依次输入以下两条命令

    cd docs
    sphinx-quickstart

    执行完毕后项目中自动新增这些:
  2. 打开 conf.py 做如下配置修改
    将路径位置更改为: 将扩展添加如下 接着打开 index.rst 添加 calc 模块,注意这里的模块就是你自己的 python 文件,不写扩展名

以上均配置完毕后就可以用 make html 命令来生成 HTML 文档文件了:

1
make html

由于之前在 index.rst 文件中设置的是 randoms 模块,因此创建失败,提示模块 randoms 没有找到 No module named ‘randoms’
要在 index.rst 中把 randoms 改为 calc

还是提示找不到 calc 模块的信息

这也许是由于路径描述的错误,在 conf.py 中修改路径位置为

以上完事之后再次make html
build 目录的状态,成功生成 html 文档

自动创建了许多HTML文件,直接打开 index.html 就可以查看 Docstring 了

魔法__slots__的妙用

Posted on 2020-01-08 | In Python进阶 |

slots的中文解释

在Python中,slots是一个牛逼的魔法关键词
它更多的是用于面向对象的类和实例中,发挥以下三点重要作用

  1. 快速访问类的属性
  2. 限制类的实例属性
  3. 优化内存

一、快速访问类的属性

一般说来定义用实例一个类如下操作

现在加入 __slots__ 魔法

加不加魔法有什么区别呢?
现在用 timeit 的 repeat 方法执行个 100W 次试试看

  • 先来看不加__slots__魔法的情况 运行后可以看到所需要的时间是:
  • 现在加入__slots__来运行一次 从运行时间比较得出,加不加__slots__魔法对程序执行效率影响较大,加魔法后运行速度更快了,这就是所谓的快速访问类的属性。

二、限制类的实例属性

通常情况下,类的实例化及属性访问是这样的:

现在有个新的概念
动态绑定
是什么意思呢?就是实时增加实例的属性,如下搞法:
临时增加了实例对象的 playgame 属性,并成功访问

如果不允许任意增加对象的属性,就要用__slots__ 魔法进行限制,此例中只允许 name age sex 三个属性,不能追加其它任何属性了

通过魔法对对象属性进行了严格的限制,再运行会报错,成功限制了实例属性:

三、优化内存

这里使用 memory_profiler 来测量内存消耗,实例化 100W 次
不加__slots__魔法内存消耗如下:

加上__slots__魔法的情况如下:
可以看到存在消耗明显减少,这就是__slots__的优势

sys模块常用文件操作

Posted on 2020-01-06 | In Python进阶 |

sys模块主要是提供一些变量、函数跟Python解释器进行有效交互。

如:判断当前的解释器是不是最终版本,如此判断
如果解释器是版本3则执行导入,否则不导入

命令行解释执行:

  • sys.argv
    argv 会返回一个 list, 这个 list 的第一个元素是程序的路径,如下图所示:

    命令行解释执行:

    通过命令行让程序接收多个参数
    在运行脚本后面输入空格分隔的参数,可以被 sys.argv 接收到。方便程序和使用者进行交互

    比如有一人下载程序会根据用户输入的参数进行下载:

    同样用命令行交互方式代入需要的参数

  • sys.path
    获取 python 环境变量有位置

  • sys.platform
    获取你的 Python 运行的系统版本:
    通过此命令实现在特定的环境做一些不同的执行:

  • sys.modules.keys()
    获取系统已经导入的模块名称:

  • sys.version
    获取系统的版本

  • sys.exit()
    退出 python 当前程序

需要获取全部使用说明,同样用 help 命令查看

OS模块的常用文件操作

Posted on 2020-01-03 | In Python进阶 |

操作系统Operating System
Python 常用 OS 库模块操作

  1. 获取当前路径
    os.getcwd():
  2. 创建目录
    os.mkdir():
    通过此命令创建了 test 目录如下:
  3. 修改目录名称
    os.rename(‘旧目录名’, ‘新目录名’):
    通过此命令修改 test 为 test2
  4. 删除目录
    os.rmdir(‘要删除的目录’)
    可以看到成功删除了 test2 目录
  5. 进入目录
    os.chdir():
    创建目录 -> 进入目录 -> 输出当前路径
  6. 判断目录是否存在
    os.path.exists():
    先获取当前路径 -> 当前路径就是 test, 其下层没有其它目录,所以返回 False ,
    于是切换回上一层目录,Python37-32 目录包含 test 目录 返回 Ture
  7. 列出当前目录的文件
    os.listdir():
    可以看到命令支持 相对路径 和 绝对路径 描述。
    此命令把当前路径下的全部 目录 和 文件 全盘罗列出来了
  8. 列出当前目录下的目录
    1
    [x for x in os.listdir('./') if os.path.isdir(x)]

同理,列出当前目录下的所有文件

1
[x for x in os.listdir('./') if os.path.isfile(x)]
  1. 列出当前目录下的指定文件
    列出所有 txt 文件:
    1
    [x for x in os.listdir('./') if os.path.isfile(x) and os.path.splitext(x)[1] == '.txt']
  1. 获取系统信息
    os.name Linux 系统显示 posix , Windows 显示 nt

OS 模块更多的使用信息采用 help 命令去查看

各种帮助文档的写法

Posted on 2019-12-24 | In Python进阶 |

什么是 Docstring

其实就是文档字符串,主要就是解释项目中的具体功能使用介绍,项目超详细的使用说明书
通过 help 命令查看 print 函数的使用说明

Docstring 也是在代码里直接写的,与注释不同的在于写法不同,描述的方式不同,Docstring 更多的是描述具体的功能,而注释更多的是解释代码的行为

查看 print 函数源码,得知其 Docstring 的写法如下:

  1. Docstring 应该是在函数定义下的第一行开始声明(类也是如此)

  2. Docstring 应该是用三引号开头三引号结尾

  3. Docstring 第一行的描述尽量简短并且能让人一下子就知道说的是什么

  4. 第二行起需要空行

  5. 每一段描述之间需要有空行

创建一个简单的模块

查看这个模块的帮助文档

使用协程实现并发

Posted on 2019-12-06 | In Python进阶 |

协程的理解

来个简单代码

执行结果:

现在我们为程序加上协程
注意查看代码区别

执行结果:

注意看这段代码,
在这里我们导入了一个 asyncio 模块,
它可以让我们使用到协程,
我们在 main 这个函数的前面加了一个关键词: async ,
这样就使得这个函数变成了一个异步函数,
也就是说,现在的 main 变成了一个协程对象,
可以打印一下看:

这里的 coroutine 就是协程的意思

我们继续看这个异步函数,
在里面我们定义了一个关键词: await ,
它能够将执行阻塞在这里,
但执行完毕的时候才会返回,
比如这里我们是让它等待一秒才去执行打印 “人生苦短,我用Python”。

最后我们通过 asyncio.run(main()) 来运行这异步函数。

不过,这段代码运行到最后,
也是 5 秒多啊,使用协程没有变快?

这是因为我们通过 asyncio.run() 去执行 main 函数的时候,
每次都遇到 wait ,然后就阻塞在这里,完了才继续。
每次都只执行一个任务,所以这段代码和我们一开始写的没什么两样…

使用协程代码改进

那他妈的用这协程写这样的代码不就是画蛇添足么?
别着急嘛,我这不是先跟你说说它的写法,
接下来我们要让程序变快,
协程就应该创建多个任务去执行,
所以我们要使用到
asyncio.create_task 方法,
我们继续对刚刚的代码进行改进:

运行结果:

主要来看一下 task 这个异步函数,
我们在里面通过 for 循环然后使用 asyncio.create_task 创建了 5 个任务,
注意,我们在这里面传入的是 main 这个异步函数,
当任务被创建的时候,它就会去调度 main 函数了。

而后我们执行了:

这样就能实现:等所有的任务执行完毕再继续往下执行
等创建的5个任务执行完毕再继续往下执行。
即先调度完成 5 个 main 函数,
打印出“Python带我飞!”
而后再继续往下执行打印”人生苦短,我用Python“
从运行结果看

执行逻辑解释
值得注意的是,
这里的 “Python带我飞!” 是在你 main 函数的
await asyncio.sleep(1) 之前,
所以每一个任务执行到这里的时候,
遇到 await 就会的当前任务就会跳出,
开始调度下一个任务,
1 秒钟过后,
事件调度器就会重新调度一开始的任务,
往下执行 “人生苦短,我用Python”。

先打印了五个:Python带我飞!红框
然后等待1秒
后打印了五个:人生苦短,我用Python 蓝框
结果总耗时为:1 秒
这里的时间是 main 函数控制的,
即 main 函数的

改为 3 秒,就耗时3秒

通过协程的方式,
可以有效的去高效的执行并发任务,
通过 asyncio 模块的
await 和 create_task 方式来有效控制任务的切换。

执行多线程多进程后得到的Future操作

Posted on 2019-12-05 | In Python进阶 |

多进程submit

当执行 executor.submit 方法之后
我们会得到一个 Future 对象:

这些个 Future 对象封装了
一些异步操作的方法
常常会用的有这么几个:

1、 done() :
如果调用已被取消或正常结束那么返回 True 。
2、result(timeout=None):
返回调用返回的结果。
3、add_done_callback(fn):
当 future 被取消或完成运行时,将会调用 fn 方法。
4、as_completed(fs):
当 future 执行完之后会返回一个迭代器。

此代码开启最多 5 个线程执行
每一次 submit 就会得到一个 Future
future 里存放的的爬取数据
接下来可以对 future 做进一步操作

add_done_callback 方法

比如当它执行完成的时候去回调一个 done 方法。
要实现此功能就要使用 future 的
add_done_callback 方法

可以看到
每次 submit 都会调用到自定义的 done 方法

放入队列等待执行

将每次的 future 放入队列等待执行
这时每个 future 里就是我们爬取的数据了
就可以分别对其进行数据解析,
得到我们想要的数据
将数据存入 Excel 、数据库等等

123…5

LST

Python编程学习, 程序化思维提升, 总结

43 posts
7 categories
222 tags
© 2020 LST
Powered by Hexo
|
Theme — NexT.Muse v5.1.4