我实现的对不对?
现在,大家已经完成了第一个题目。这个题目当然是很简单的,但之后随着知识的增多,我们要完成的题目也越发复杂。那么有没有什么方法能检验我们写的代码对不对呢?
手动测试代码
回想一下,doctest描述了“当我们在交互模式下这样输入代码,就会得到这样的结果”,那么我们是不是可以打开交互模式,按照doctest的描述输入代码,然后观察结果是不是一致的呢?
是的!我们可以打开一个交互模式的 python,然后把作业文件粘贴进去,最后按一下回车,python就把文件的代码运行完了。然后,我们就可以对照着 doctest 输入 doctest 即可测试:
$ python
>>> def twenty_twenty_four():
... """Come up with the most creative expression that evaluates to 2024,
... using only numbers and the +, *, and - operators.
...
... Expected result:
... >>> twenty_twenty_four()
... 2024
... """
... return 2024
...
>>>
>>> def sum(a, b):
... """Compute the sum of a and b.
...
... Expected result:
... >>> sum(1, 2)
... 3
... >>> sum(3, 8)
... 11
... """
... return ______
...
>>>
>>> def diff_square(a, b):
... """Compute the difference of square a and square b.
...
... Expected result:
... >>> diff_square(3, 2)
... 5
... >>> diff_square(3, 4)
... -7
... """
... return ______
...
>>> twenty_twenty_four()
2024
这和doctest描述的一模一样,所以你现在可以松口气,相信自己的代码是对的了。如果发现不一样,你就需要看看自己哪里出问题了。
刚才其实有一个概念的陷阱。现在让我们思考一个问题:为什么说,经过刚才这样一个过程,我们就有理由相信我们的代码是对的呢?
实际上,“相信自己的代码是对的”是一个错误的说法!准确的说,大家只能有理由相信“自己写的代码和doctest所预期的相符合”,进而推论,自己的代码可能是对的。
其实,像这样一个比较代码的实际执行结果和预期结果的过程就叫做测试(Testing)。这也是“doctest”中test的中文含义。
测试不能保证代码是对的,只能保证代码在多大程度上与预期相符合。但如果通过了足够多、足够复杂的测J试,我们就更加有信心,更容易相信我们的代码是对的。 反过来讲,如果代码连基本的测试都没有通过,说明肯定不是对的。
当然有!
- 形式化验证(Formal Verification),通过逻辑和推理规则(而非一个一个的测试样本)来证明程序的正确性。这种技术在涉及生命财产安全的领域有更广泛的运用。
- 静态分析(Static Analysis),通过抽象和近似来确保程序的安全性。这种技术在当今流行的 IDE、代码编辑器和编译器中都有广泛的运用。
使用Ok进行自动化测试
随着大家做的题目越来越多、越来越复杂,同学们可能会发现,每当自己写了一段新的代码,就要重新走上面一套doctest的流程,这样会非常麻烦。
程序员都是懒惰的生物,嫌麻烦是人类的天性,这也是为什么我们要开发各种各样的减轻负担的工具。 为了减轻同学们测试的负担,tygg 开发了 SICP 插件。在前面的章节中我们也介绍了插件的安装。
为什么我点击
Run
(或者Debug
)打开了浏览器,访问了南京大学代码托管系统?
Ok不仅是一个测试工具,我们还需要用它提交作业。 提交作业时,我们通过南京大学代码托管系统的登陆信息来辨别各个人。 在下一节中我们会介绍怎么注册系统并提交作业,现在不需要管。
助教会如何测试我的代码?
对于助教来说,很难一一审查每个人的代码来验证大家写得正不正确,所以我们会采用测试的方法来给大家评分。像我们发布给同学的doctest一般都写得比较简单,所以那些写得不正确的代码也有可能通过doctest,比如像下面这段代码,本来助教希望大家写return a + b
,但有个小机灵鬼直接返回3
试图蒙混过关:
def add(a, b):
"""return the sum of a and b
>>> add(1, 2)
3
"""
return 3
但如果我们的测试写得越“详细”,写得不正确的代码就越难蒙混过关。 同学们可以试试下面这段代码能不能通过 doctest。
def add(a, b):
"""return the sum of a and b
>>> add(1, 2)
3
>>> add(3, 4)
7
"""
return 3
因此,助教们设置了一个在线测评(Online Judge, OJ)网站,用更加“详细”的、对大家隐藏起来的测试来给大家评分,尽可能防止不正确的代码蒙混过关,维护认真做实验的同学的权利。我们会在下一节中教大家如何提交作业,让助教测试你的代码。