= 2006-03-26 校对记要 = <> '''校对文件''': roman.xml '''章节''': [[http://www.woodpecker.org.cn/obp/diveintopython-zh-5.4/zh-cn/dist/htmlflat/diveintopython.html#roman2|第15章]] == 本章目录 == Chapter 15. Refactoring 重构 * 15.1. Handling bugs bugs 处理 ^处理bug^ * 15.2. Handling changing requirements 应对 要求^需求^变化 * 15.3. Refactoring 重组 ^重构^ * 15.4. Postscript 后记 * 15.5. Summary 小结 == 第15章第1节 == [[http://www.woodpecker.org.cn/obp/diveintopython-zh-5.4/zh-cn/dist/htmlflat/diveintopython.html#roman.bugs]] '''第一段''' * Despite your best efforts to write comprehensive unit tests, bugs happen. What do I mean by “bug”? A bug is a test case you haven't written yet. * 尽管你很努力 的^地^编写全面的单元测试,但是 bug 还是会出现。 我所说的 “bug” 是什么呢? Bug 是你还没有编写的--(一个)-- 独立测试^测试用例^。 JasonXie 同意 ---- '''Example 15.1. The bug''' * Example 15.1. The bug * 例 15.1. 关于^一个^ Bug JasonXie ^一个^不需要翻译出来吧! ---- '''Example 15.1.说明1''' * Remember in the previous section when you kept seeing that an empty string would match the regular expression you were using to check for valid Roman numerals? Well, it turns out that this is still true for the final version of the regular expression. And that's a bug; you want an empty string to raise an InvalidRomanNumeralError exception just like any other sequence of characters that don't represent a valid Roman numeral. * 在前面的 章节中 你 看到^你有注意到一个空字符串会匹配^ 用以^那个^检查罗马数字有效性的正则表达式--(认为空字符串有效)--了吗? 对于最终版本中的正则表达式这一点仍然没有改变。这就是一个 Bug ,你希望--(对于)--空字符串能够像--(对待)--其他无效的罗马数字表示一样引发 InvalidRomanNumeralError 异常。 JasonXie 同意 ---- '''下一段''' * After reproducing the bug, and before fixing it, you should write a test case that fails, thus illustrating the bug. * 在 再现 ^重现这个^ Bug 和 去除^修改^它之前你应该编写一个 失败独立测试^会失败的测试用例^来 描述这个 Bug^说明它^。 JasonXie 同意 ---- '''Example 15.2.说明1''' * Pretty simple stuff here. Call fromRoman with an empty string and make sure it raises an InvalidRomanNumeralError exception. The hard part was finding the bug; now that you know about it, testing for it is the easy part. * 这里很简单。以空字符串调用 fromRoman 并确保 ^它会^引发一个 InvalidRomanNumeralError 异常。 难点在于找出 Bug, 现在你知道了它^既然你已经知道它了^,测试它就很 简单^容易^了。 JasonXie 同意 ---- '''下一段''' * Since your code has a bug, and you now have a test case that tests this bug, the test case will fail: * 因为你的代码 存在^有^一个 Bug,并且你编写了测试这个 Bug 的 独立测试^测试用例^,所以 独立测试^测试用例^将会失败: JasonXie 意思一样,‘存在’ 好像好听一些 ---- '''Example 15.3. ''' * Output of romantest61.py against roman61.py * 以 ^用^romantest61.py 测试 roman61.py 的 输出 ^结果^ JasonXie 同意 ---- '''Example 15.4. Fixing the bug (roman62.py)''' * This file is available in py/roman/stage6/ in the examples directory. * 这个文件可以 从 ^在例子目录下的^ py/roman/stage6/ --(的 examples)-- 目录中 获得 ^找到^ 。 JasonXie 同意 ---- '''Example 15.4. 说明1''' * Only two lines of code are required: an explicit check for an empty string, and a raise statement. * 只需要两行代码: 直白的^一行直接^检查空字符串和一 条^行^ raise 语句。 JasonXie 同意 ---- '''Example 15.5.''' * Output of romantest62.py against roman62.py * 以 ^用^romantest62.py 测试 roman62.py 的 输出 ^结果^ JasonXie 同意 ---- '''Example 15.5. 的说明''' * The blank string test case now passes, so the bug is fixed. * 空字符串 独立测试^测试用例^现在通过了,说明 Bug 被改正了。 * All the other test cases still pass, which means that this bug fix didn't break anything else. Stop coding. * 所有其他 独立测试^测试用例^依然通过,证明这个 Bug 修正没有影响到其他部分。 停止编程^不需要再编程了^。 JasonXie 同意 ---- '''最后一段''' * Coding this way does not make fixing bugs any easier. Simple bugs (like this one) require simple test cases; complex bugs will require complex test cases. In a testing-centric environment, it may seem like it takes longer to fix a bug, since you need to articulate in code exactly what the bug is (to write the test case), then fix the bug itself. Then if the test case doesn't pass right away, you need to figure out whether the fix was wrong, or whether the test case itself has a bug in it. However, in the long run, this back-and-forth between test code and code tested pays for itself, because it makes it more likely that bugs are fixed correctly the first time. Also, since you can easily re-run all the test cases along with your new one, you are much less likely to break old code when fixing new code. Today's unit test is tomorrow's regression test. * 这样编程,并没有令 Bug 修正变得简单。 简单的 Bug (就像这一个)需要简单的 独立测试 ,复杂 Bug 则需要复杂的 独立测试 。 在测试为核心的氛围下,这 看起来^好像^ --(似乎)--延长了修正 Bug 的时间,因为你需要先贴切地描述出 Bug (编写 独立测试 )然后才去修正它。 如果 独立测试 没能正确通过,你需要思量这个修改错了还是 独立测试 本身出现了 Bug。无论如何,从长远上讲,这样在测试代码和代码之间的反复是值得的,因为 通常^这样会使^ Bug 在第一 次就被修正过来了^时间就被修正的可能性大大提高^。 当然^而且^,由于任何新的更改后你都可以轻易 的^地^重新运行 所有 独立测试 ,新代码 对老代码产生负面影响^破坏老代码^的机会也变得微乎其微。 今天的单元测试就是明天的 衰退^回归^测试(regression test)。 * {i} 独立测试 (!) 测试用例 (!) JasonXie 同意