TDD @

~ 粗谈 Pythonic 测试


Zoom.Quiet


是也乎...





幻灯地址:http://py.kingsoft.net/s5/100826-PyTDD/
...

S5

免责聲明
山寨的,非业界公认的,个人体验为基础!

伙同所有同好行者总结而得

  • 一切资料来自网络互动挖掘
  • 一切想法来自日常学习工作
  • 一切体悟来自各种沟通交流
  • 一切知识来自社区分享印证
  • 一切经验来自个人失败体验
    ......
class="incremental"...

< /7+-2>
单位时间可以记住的只有7+-2 个

  1. just Test now!
  2. 咋想测试这事儿
  3. Py相关测试工具
  4. TDD不是玩笑...
  5. 代码复审比测试靠谱

< TDD>
本质->工具->实例->思考

class="incremental"...

Test-driven development:by example

$(document).ready(function() {
	$("img[class='attachment']").each(function(){
	    $(this).attr("usemap","#"+$(this).attr("alt"));
    });
});

< TDD流程>

起意...

求素数

起意...
创建 primenu.py

# -*- coding: utf-8 -*-
'''判定是否素数
>>> chkPrime(5)
True
>>> chkPrime(4)
False
'''
def chkPrime(N):
    pass
if __name__ == '__main__':# this way the module can be
    import doctest
    doctest.testmod()

败!先...

$ python primenu.py 
**********************************************************************
File "primenu.py", line 3, in __main__
Failed example:
    chkPrime(5)
Expected:
    True
Got nothing
**********************************************************************
File "primenu.py", line 5, in __main__
Failed example:
    chkPrime(4)
Expected:
    False
Got nothing
**********************************************************************
1 items had failures:
   2 of   2 in __main__
***Test Failed*** 2 failures.

最友好的实验环境 ;-)

IPython 0.10 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object'. ?object also works, ?? prints more.

In [1]: %doctest_mode
*** Pasting of code with ">>>" or "..." has been enabled.
Exception reporting mode: Plain
Doctest mode is: ON
>>> %
%Exit       %debug        %logstop   %prun      %runlog
%Pprint     %dhist        %lsmagic   %psearch   %save
%Quit       %dirs         %macro     %psource   %sc
%alias      %doctest_mode %magic     %pushd     %store
%autocall   %ed           %p         %pwd       %sx
%autoindent %edit         %page      %pycat     %system_verbose
%automagic  %env          %paste     %quickref  %time
%bg         %exit         %pdb       %quit      %timeit
%bookmark   %hist         %pdef      %r         %unalias
%cd         %history      %pdoc      %rehash    %upgrade
%clear      %logoff       %pfile     %rehashx   %who
%color_info %logon        %pinfo     %rep       %who_ls
%colors     %logstart     %popd      %reset     %whos
%cpaste     %logstate     %profile   %run       %xmode

素数是除1和自个儿外都不能整除的数...

>>> N=5
>>> N%4
1
>>> N%5
0
>>> range(2,5)
[2, 3, 4]
>>> [N%d for d in range(2,N)]
[1, 2, 1]
>>> 0 not in [N%d for d in range(2,N)]
True
>>> N =4
>>> 0 not in [N%d for d in range(2,N)]
False

完善代码
使用iPython 探查出的成果 ;-)

# -*- coding: utf-8 -*-
'''判定是否素数
>>> chkPrime(5)
True
>>> chkPrime(4)
False
'''
def chkPrime(N):
    return 0 not in [N%d for d in range(2,N)]
if __name__ == '__main__':# this way the module can be
    import doctest
    doctest.testmod()

通过测试!

$ python primenu.py 
$ python primenu.py -v
Trying:
    chkPrime(5)
Expecting:
    True
ok
Trying:
    chkPrime(4)
Expecting:
    False
ok
1 items had no tests:
    __main__.chkPrime
1 items passed all tests:
   2 tests in __main__
2 tests in 2 items.
2 passed and 0 failed.
Test passed.

需求变更
找出指定范畴中的所有素数!?

# -*- coding: utf-8 -*-
'''判定是否素数
>>> chkPrime(5)
True
>>> chkPrime(4)
False

#   找出所有素数
>>> foundPrime(10)
[2, 3, 5, 7]
'''
def foundPrime(N):
    pass
def chkPrime(N):
    return 0 not in [N%d for d in range(2,N)]
if __name__ == '__main__':# this way the module can be
    import doctest
    doctest.testmod()

当然要败!

$ python primenu.py 
**********************************************************************
File "primenu.py", line 9, in __main__
Failed example:
    foundPrime(10)
Expected:
    [2, 3, 5, 7]
Got nothing
**********************************************************************
1 items had failures:
   1 of   3 in __main__
***Test Failed*** 1 failures.

通过就地定义函式进行探测

>>> def chkPrime(N):return 0 not in [N%d for d in range(2,N)]
... 
>>> N=5
>>> chkPrime(N)
True
>>> [P for P in range(2,N) if chkPrime(P)]
[2, 3]
>>> def foundPrime(N):
...     return [P for P in range(2,N) if chkPrime(P)]
... 
>>> foundPrime(5)
[2, 3]
>>> foundPrime(10)
[2, 3, 5, 7]

增补代码
从iPython 的实验成果直接利用!

# -*- coding: utf-8 -*-
'''判定是否素数
>>> chkPrime(5)
True
>>> chkPrime(4)
False

#   找出所有素数
>>> foundPrime(10)
[2, 3, 5, 7]
'''
def foundPrime(N):
    return [P for P in range(2,N) if chkPrime(P)]
def chkPrime(N):
    return 0 not in [N%d for d in range(2,N)]
if __name__ == '__main__':# this way the module can be
    import doctest
    doctest.testmod()

再次成功!
之前的测试确保了原有代码靠谱!

$ python primenu.py
$ python primenu.py -v
Trying:
    chkPrime(5)
Expecting:
    True
ok
Trying:
    chkPrime(4)
Expecting:
    False
ok
Trying:
    foundPrime(10)
Expecting:
    [2, 3, 5, 7]
ok
2 items had no tests:
    __main__.chkPrime
    __main__.foundPrime
1 items passed all tests:
   3 tests in __main__
3 tests in 3 items.
3 passed and 0 failed.
Test passed.

对应到各个函式的聲明区

# -*- coding: utf-8 -*-
'''素数相关模块
'''
def chkPrime(N):
    '''判定是否素数
    >>> chkPrime(5)
    True
    >>> chkPrime(4)
    False
    '''
    return 0 not in [N%d for d in range(2,N)]
def foundPrime(N):
    '''找出所有素数
    >>> foundPrime(10)
    [2, 3, 5, 7]
    '''
    return [P for P in range(2,N) if chkPrime(P)]
if __name__ == '__main__':      # this way the module can be
    import doctest
    doctest.testmod()

测试相应变化
有利于测试业务分离...

$ python primenu.py -v
Trying:
    chkPrime(5)
Expecting:
    True
ok
Trying:
    chkPrime(4)
Expecting:
    False
ok
Trying:
    foundPrime(10)
Expecting:
    [2, 3, 5, 7]
ok
1 items had no tests:
    __main__
2 items passed all tests:
   2 tests in __main__.chkPrime
   1 tests in __main__.foundPrime
3 tests in 3 items.
3 passed and 0 failed.
Test passed.

< /TDD流程>

究竟什么是测试?

测试?

究竟什么是测试?

究竟什么是测试?

测试的本原思路

< 5W>

测试主体
人!

什么

测试实施
所有人!

测试时机
单元

何时

测试地点
就地!

在哪

测试动机
懒...

为嘛

测试的本原思路

< /5W>

重在衡量工程质量的话...

重在探查隐藏问题的...

测试全景...

SoftwareTestFullPanoramicChart-1.gif

测试全景...

(*_*)b

SoftwareTestFullPanoramicChart-1.gif

< TDD>
本质->工具->实例->思考

不屌代码

< 黑盒>

< Browser>

JavaScript
一个跨浏览器 (IE, Firefox, Safari) JavaScript 程序,记录浏览器事件 (点击和输入文字等)
以及测试断言 (这个文本框应包含这个文字,那个复选框应不应被勾选等)
依赖 Zope/

zope
.testrecorder

模拟浏览器
脱离 Zope 单独使用。支持简单 DOM (含表单)、Cookie、定制 HTTP 请求

zope
.testbrowser

模拟浏览器
配合 PyUnit:DOM 方面仅支持表单,其他能力与 zope.testbrowser 相当

WebUnit

驱动IE
从 M$ OS

Py IE Automation

stands for Python Automated Module For I.E.

PAMIE

Python 与 XPCOM通信!
for Gecko

PyXPCOM

脚本化操作浏览器
a simple scripting language for Web browsing

twill

=>
UI测试框架

Tellurium

...
宏记录鼠标点击坐标和时间然后重放

商用

< /Browser>

Performance testing

< 性能>

< 专有/>
金山在使用的...

LoadRunnerHP ;SilkPerformer ;Rational Performance TesterIBM ;WebLoad ;QALoad ;OpenSTA ;WSAM$ ....

< 开源/>
金山在使用的...

JmeterJAVA ;WebBench ;Apache ab ;http_load ;Siege ;Curl-Loader ;p-unit ;WebStone ; ....

VisualPyTune.png

Performance testing

< /性能>

GUI in Linux

KWinAuto

自制GUI测试工具
张长荣作品...

KWinAuto

不屌代码

< /黑盒>

恨屌代码

< 白盒>

文档化测试

doctest

list of: +------+ +---------+ |module| --DocTestFinder-> | DocTest | --DocTestRunner-> results +------+ | ^ +---------+ | ^ (printed) | | | Example | | | v | | ... | v | DocTestParser | Example | OutputChecker +---------+

doctest写测试非常爽:)

                            list of:
+------+                   +---------+
|module| --DocTestFinder-> | DocTest | --DocTestRunner-> results
+------+    |        ^     +---------+     |       ^    (printed)
            |        |     | Example |     |       |
            v        |     |   ...   |     v       |
           DocTestParser   | Example |   OutputChecker
                           +---------+

xUnit 家族

< unittest>

acceptance test-driven development (ATDD)

robotframework

面向web测试框架

Windmill

框架自测

Pylons

框架自测

Django

测试框架
extends unittest to make testing easier

nose

测试框架
extends unittest to make testing easier

py.test

覆盖测试
表入迷...

thumbpy

....

< /unittest>

< Checker>

静态檢驗

PyLint

静态檢驗

Pyflakes

静态檢驗

PyChecker

静态檢驗
UML输出

PyNSource

静态檢驗
检查Python Coding风格

PEP8

< /Checker>

模拟器

< Mocks>

模拟DB

The Python Mock Class

DB模拟

Mock Objects

基于模拟的框架

Fudge

Mocks的依赖

模拟器

< /Mocks>

深入调试

< Debug>

追踪机
Linux/BSD/Darwin 都使用的进程追踪机制

python-ptrace

宇宙牌!
可以对C/C++ 的程序轻松注入各种回调勾子!是Python 这一胶水的倍增器!依赖 OllyDbg v 又一德制武器...

Universal Hooker

for M$!
对Microsoft Debug Engine 的Py包装,可以使用py脚本来自动化分析调试结果了

PyDbgEng

sqlmap
: automatic SQL injection and database takeover tool

< 可视化性能>

< 国产/>

< /可视化性能>

深入调试

< /Debug>

恨屌代码

< /白盒>

屌不屌?

< 灰盒>

模糊测试

sulley

屌不屌?

< /灰盒>

持续集成

< CI>

集成到CI平台...


; CruiseControl 和Trac
; 和Py
; HudsonTracPlugin ...

自动化部署

< Deploy>

Paste
Configuring WSGI applications and servers.

Paste

Fabric
Capistrano样的部署工具

Fabric

pip
原名pyinstall

pip

EasyInstall
setuptools 通过 .ege 进行统一部署

虚拟化环境

virtualenv

自动化部署

< /Deploy>

持续集成...

< /CI>

< /TDD>

\(^o^)/

< TDD>
本质->工具->实例->思考

测试的目标忒多:
太多 -ability

scalability ;distributability ;maintainability ;usability ;portability ;compatability ;availability ;configurability ...

distributable

可测性!

testability

无依赖!

No-dependency

maintainable

幸福的给劲模块s!

sys ;os ;StringIO ;tempfile ;optparse ;getopt ;ConfigParser ;importlib ;importers ;logging ;atexit ;traceback ;cProfile ;pstats ;hotshot ;timeit ;getopt ...

Google内部原则
70%底层接口测试和单元测试 20%集成测试,10%界面测试

7:2:1

Code review

代码
复审

trac-codereview_scrot.png

YACR
TracYetAnotherCodeReview

< /TDD>

(~_~)\\

70%的测试工作集中在底层接口测试和单元测试,20%的测试工作为集成测试,其他10%的测试即为界面测试

< Discussing>
本质->工具->实例->思考

class="incremental"...

< 参考/>

$(document).ready(function() {
	$("img[class='attachment']").each(function(){
	    $(this).attr("usemap","#"+$(this).attr("alt"));
    });
});

山寨的,非业界公认的,个人体验为基础的...

Q&A


http://py.kingsoft.net/s5/100826-PyTDD/
...

< /7+-2>
单位时间可以记住的只有7+-2 个

  1. just Test now!
  2. 咋想测试这事儿
  3. Py相关测试工具
  4. TDD不是玩笑...
  5. 代码复审比测试靠谱

< 版本 />

修订历史::
测试驱动开发(中文版) (豆瓣)
$(document).ready(function() {
	$("img[class='attachment']").each(function(){
	    $(this).attr("usemap","#"+$(this).attr("alt"));
    });
});