我从其他讨论中看到,重装被认为是不必要的操作,也是开发程序的坏方法。人们说使用doctest和unittest。我肯定错过了什么。为了开发一个程序,我把它写在一个模块中,将模块加载到Eclipse控制台中,通过运行少量代码示例在控制台中进行试验,然后在模块中发现错误或决定更改某些内容。最快的做法是保存模块,重新加载并在控制台中继续工作。
有没有更好的方法?开发程序时不使用重装的最佳方式
回答
这里有一个如何你可以在比较通过在控制台输入代码,用递归阶乘函数被用作一个实例使用doctest和测试驱动的开发与测试一个人为的例子:
控制台:
第一次尝试:
def factorial(x)
pass
控制台:
>>> factorial(7)
SyntaxError: invalid syntax
第二次尝试:
def factorial(x):
return x*x-1
控制台:
>>> factorial(7)
42
第三次尝试:
控制台:
>>> factorial(7)
RuntimeError: maximum recursion depth reached # StackOverflow! (basically)
第四次尝试:
def factorial(x):
if x == 0:
return 1
else:
return x * factorial(x-1)
控制台:
>>> factorial(5)
120
最终,我们得到正确的答案,但在每一个阶段,我们必须回到控制台和写同样的事情。对于像这样的短程序来说,这是可以的,但对于具有许多功能的程序,以及更复杂的交互和可能被测试的程序来说,这需要很长时间。编程是关于重复性任务的自动化,而测试是一个重复的任务,所以自动化它是有意义的。在Python中,为您提供的工具就是为您提供的。
看哪 - 该文档测试模块(例如,从文档拍摄)
第一次尝试:
def factorial(n):
"""Return the factorial of n, an exact integer >= 0.
>>> [factorial(n) for n in range(6)]
[1, 1, 2, 6, 24, 120]
>>> factorial(30)
265252859812191058636308480000000
>>> factorial(-1)
Traceback (most recent call last):
...
ValueError: n must be >= 0
Factorials of floats are OK, but the float must be an exact integer:
>>> factorial(30.1)
Traceback (most recent call last):
...
ValueError: n must be exact integer
>>> factorial(30.0)
265252859812191058636308480000000
It must also not be ridiculously large:
>>> factorial(1e100)
Traceback (most recent call last):
...
OverflowError: n too large
"""
if __name__ == "__main__":
import doctest
doctest.testmod(verbose=True)
首先测试(只运行程序):
Trying:
[factorial(n) for n in range(6)]
Expecting:
[1, 1, 2, 6, 24, 120]
ok
Trying:
factorial(30)
Expecting:
265252859812191058636308480000000
ok
Trying:
factorial(-1)
Expecting:
Traceback (most recent call last):
...
ValueError: n must be >= 0
ok
Trying:
factorial(30.1)
Expecting:
Traceqwrqaeqrback (most recent call last):
...
ValueError: n must be exact integer
**********************************************************************
File "C:/Python33/doctestex.py", line 14, in __main__.factorial
Failed example:
factorial(30.1)
Exception raised:
Traceback (most recent call last):
File "C:\Python33\lib\doctest.py", line 1287, in __run
compileflags, 1), test.globs)
File "<doctest __main__.factorial[3]>", line 1, in <module>
factorial(30.1)
File "C:/Python33/doctestex.py", line 32, in factorial
raise ValueError("n must be exact integer")
ValueError: n must be exact integer
Trying:
factorial(30.0)
Expecting:
265252859812191058636308480000000
ok
Trying:
factorial(1e100)
Expecting:
Traceback (most recent call last):
...
OverflowError: n too large
ok
1 items had no tests:
__main__
**********************************************************************
1 items had failures:
1 of 6 in __main__.factorial
6 tests in 2 items.
5 passed and 1 failed.
***Test Failed*** 1 failures.
>>> ================================ RESTART ================================
>>>
Trying:
[factorial(n) for n in range(6)]
Expecting:
[1, 1, 2, 6, 24, 120]
**********************************************************************
File "C:/Python33/doctestex.py", line 4, in __main__.factorial
Failed example:
[factorial(n) for n in range(6)]
Expected:
[1, 1, 2, 6, 24, 120]
Got:
[None, None, None, None, None, None]
Trying:
factorial(30)
Expecting:
265252859812191058636308480000000
**********************************************************************
File "C:/Python33/doctestex.py", line 6, in __main__.factorial
Failed example:
factorial(30)
Expected:
265252859812191058636308480000000
Got nothing
Trying:
factorial(-1)
Expecting:
Traceback (most recent call last):
...
ValueError: n must be >= 0
**********************************************************************
File "C:/Python33/doctestex.py", line 8, in __main__.factorial
Failed example:
factorial(-1)
Expected:
Traceback (most recent call last):
...
ValueError: n must be >= 0
Got nothing
Trying:
factorial(30.1)
Expecting:
Traceback (most recent call last):
...
ValueError: n must be exact integer
**********************************************************************
File "C:/Python33/doctestex.py", line 14, in __main__.factorial
Failed example:
factorial(30.1)
Expected:
Traceback (most recent call last):
...
ValueError: n must be exact integer
Got nothing
Trying:
factorial(30.0)
Expecting:
265252859812191058636308480000000
**********************************************************************
File "C:/Python33/doctestex.py", line 18, in __main__.factorial
Failed example:
factorial(30.0)
Expected:
265252859812191058636308480000000
Got nothing
Trying:
factorial(1e100)
Expecting:
Traceback (most recent call last):
...
OverflowError: n too large
**********************************************************************
File "C:/Python33/doctestex.py", line 22, in __main__.factorial
Failed example:
factorial(1e100)
Expected:
Traceback (most recent call last):
...
OverflowError: n too large
Got nothing
1 items had no tests:
__main__
**********************************************************************
1 items had failures:
6 of 6 in __main__.factorial
6 tests in 2 items.
0 passed and 6 failed.
***Test Failed*** 6 failures.
那么当我们完成程序(以及之间的所有阶段),我们只需按一个按钮,即可完成我们所有的测试。如果您正在与一个团队合作开发一个更大的项目,那么您可以将测试数据写入文件并使用失败来查看需要关注的位置。
Trying:
[factorial(n) for n in range(6)]
Expecting:
[1, 1, 2, 6, 24, 120]
ok
Trying:
factorial(30)
Expecting:
265252859812191058636308480000000
ok
Trying:
factorial(-1)
Expecting:
Traceback (most recent call last):
...
ValueError: n must be >= 0
ok
Trying:
factorial(30.1)
Expecting:
Traceback (most recent call last):
...
ValueError: n must be exact integer
ok
Trying:
factorial(30.0)
Expecting:
265252859812191058636308480000000
ok
Trying:
factorial(1e100)
Expecting:
Traceback (most recent call last):
...
OverflowError: n too large
ok
1 items had no tests:
__main__
1 items passed all tests:
6 tests in __main__.factorial
6 tests in 2 items.
6 passed and 0 failed.
Test passed.
和(前提是您添加的所有测试用例文档字符串),现在你可以运送或整合或任何程序,它少得多的错误比,如果你只是测试你觉得要紧的事情就真是每次你改变了一些东西,而不是你在开发过程开始时可能会遇到的事情。
更不用提你现在有你的文档的基础!在控制台中运行该程序,然后进入help(factorial)
现在给你这样的:
Help on function factorial in module __main__:
factorial(n)
Return the factorial of n, an exact integer >= 0.
>>> [factorial(n) for n in range(6)]
[1, 1, 2, 6, 24, 120]
>>> factorial(30)
265252859812191058636308480000000
>>> factorial(-1)
Traceback (most recent call last):
...
ValueError: n must be >= 0
Factorials of floats are OK, but the float must be an exact integer:
>>> factorial(30.1)
Traceback (most recent call last):
...
ValueError: n must be exact integer
>>> factorial(30.0)
265252859812191058636308480000000
It must also not be ridiculously large:
>>> factorial(1e100)
Traceback (most recent call last):
...
OverflowError: n too large
然后,您可以使用一些工具(pydoc是一个标准库)打开文档字符串成格式化的HTML帮助文档。
当然,这只是您可以在Python中使用的许多测试工具之一。其他功能包括功能更强大的unittest模块,以及将assert
语句添加到代码中的功能较弱的技术。
感谢您的全面讨论。这很有趣,你可能猜到的人是Python的noob(尽管不是数学编程的noob)。我的第一种方法是将函数写入文件,导入,运行,编辑,重新加载,运行,编辑等。为了检查我是否正确理解,doctest的优点是同样快速地做同样的事情并带来额外的好处,还是稍微慢一点,但认为值得的额外严谨? – hfffoman
@hfffoman我会说'doctest'的好处是你在开始时做了更多的工作,但是这样可以减少长时间的写入测试 - 文件 - 然后 - 运行 - 它的周期以及其他好处(文档被写入随你走)。但是我认为,测试工具的威力随着程序越大而变得越明显 - 如果没有正式的测试和工具,你永远不会想要编写一个大型项目(比如说Eclipse),这可能比标准库中的更重。 – rlms
基本上不是在控制台中尝试一下,而是通过编写测试来尝试一些事情。这几乎与键入的量相同,但是可重复(您可以检查更改后是否仍然有效),并且它可以作为文档的基本形式。
+1是否意味着在一个文件中写入语句,然后在将它们变成函数之前先运行它们?那么最快的方法是将测试文件加载(并重新加载)到控制台中? – hfffoman
- 1. 开发android应用程序的最佳方式?
- 2. 使用C#+ WPF + MVVC + prism 4开发Windows应用程序的最佳方式?
- 3. 开始使用Mac开发的最佳方式
- 4. 开发群聊室的最佳方式
- 5. 调试发布模式应用程序的最佳方式
- 6. 应用程序的最佳方式
- 7. 开发GPS应用程序的最佳方法
- 8. 处理WP7应用程序开发的最佳方法?
- 9. 开始学习Web应用程序设计的最佳方式
- 10. 使用vim进行Cocoa开发的最佳方式是什么?
- 11. 在Erlang(和Riak)开发应用程序时的最佳实践?
- 12. 使用SQLite开发AIR应用程序的最佳做法
- 13. 聊天应用程序 - 最佳方式
- 14. 规划和组织C应用程序开发的最佳方式是什么?
- 15. 最佳Windows应用程序开发替代方案
- 16. Android开发:保持开发文件的最佳方式
- 17. 通过Java应用程序发布到twitter的最佳方式
- 18. 发布Rails应用程序的最佳方式
- 19. 分发Java应用程序的最佳方式是什么?
- 20. 为Web开发人员开始桌面应用程序开发的最佳方式
- 21. 在活动开始前一小时触发的最佳方式
- 22. 分配使用JNI的应用程序的最佳方式
- 23. Dockerfile:运行本地安装程序脚本的最佳方式?
- 24. 当使用AntiXssEncoder.UrlEncode时使用+而不是%20的最佳方式
- 25. Installshield安装要求(搜索已安装应用程序的最佳方式)
- 26. 在启动时启动应用程序的最佳方式?
- 27. 为桌面应用程序使用javascript api的最佳方式
- 28. 使用Traversal制作子应用程序的最佳方式
- 29. 使用Javascript构建多页应用程序的最佳方式
- 30. 在Cocoa应用程序中使用XML-RPC的最佳方式?
听说过测试驱动的Devlopment不同于Tickering驱动编程 –
Doctest和unittest适用于测试。运行代码的小部分代码不太可能捕捉到所有的错误,但这并不够方便。 – rlms
@sweeneyrod我同意有条件的测试有一个重要的地方,但有时候我不想编写最后一段代码,我只是想试验。即使在程序开发早期想制作一些经过适当测试的东西,我只想尝试并尝试不同的想法。在那个阶段,我不会认为doctest会非常有用。这只会让我放慢脚步。 – hfffoman