根据 TDD 在回文上进行单元测试

Unittest in according to TDD on Palindrome

提问人:SPGA 提问时间:9/20/2023 最后编辑:RobertSPGA 更新时间:9/20/2023 访问量:57

问:

我是 QA 的学生,现在我尝试基于 TDD 和 unittest 用 Python 编写回文代码。

我试图编写代码,它功能正常,但它无法根据,我也检查了.assertTrueassertEqual

Python 代码:

def PalindromTest(string):
    return string == string[::-1]

while True:
    stringul = input ("Enter a string or number:\n")
    string = stringul.replace(" ", "").lower()
    Test = PalindromTest(string)

    if Test == True:
        print (f'"{stringul} value is a palindrom"')
    else:
        print (f'"{stringul} value is not a palindrom"')

测试:

import unittest;
from Asignment_TDD import PalindromTest;

class MyPalindrome (unittest.TestCase):
    def test_palindrome (self):
        self.assertTrue (PalindromTest("civic"), "civic")

if __name__=='__main__':
    unittest.main()

请帮我写正确版本的 Unittest

蟒蛇 TDD

评论


答:

1赞 Robert 9/20/2023 #1

好吧,该代码显然不是以 TDD 风格编写的:-)

单元测试需要自动化,因此测试和被测代码都不应要求输入。(如果被测试的代码表现不佳,并且您无法阻止它询问,请尝试自动为其提供输入。但这可能还太先进了。

这样一来,我就会删除要求输入的循环,或者将其移动到其他地方,或者用检查来保护它,就像你在测试用例中所做的那样。这样一来,它就不会仅仅因为其他程序对被测代码进行运行。除非你正在编写一个不会在其他地方重用的脚本,否则你可能应该一直拥有它。一旦你这样做了,你的测试就会运行并通过。我现在会为不是回文的文本添加另一个测试,并断言代码正确返回 .while True:if __name__=='__main__':importif __name__=='__main__':False

def PalindromTest(string):
    return string == string[::-1]

if __name__=='__main__':
    while True:
        stringul = input ("Enter a string or number:\n")
        string = stringul.replace(" ", "").lower()
        Test = PalindromTest(string)

        if Test == True:
            print (f'"{stringul} value is a palindrom"')
        else:
            print (f'"

运行:

$ python3 test.py 
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

说到我会做什么:我也会坚持 Python 命名约定。这将使您的代码更易于理解。

1赞 Mark Seemann 9/20/2023 #2

如果要遵循测试驱动开发 (TDD),请先编写一个测试。

例如,您可以编写以下测试:

def test_civic (self):
    self.assertTrue (PalindromTest("civic"), "civic should be a palindrome")

请注意,第二个参数 to 不是任何预期值,而是一条有用的错误消息,您可以为自己(或他人)的利益编写。assertTrue

按照红-绿-重构清单,你现在在受测系统 (SUT) 中编写你能想到的最简单的代码:

def PalindromTest(string):
    return False

由于您首先需要看到测试失败,因此您可以返回 .然后运行测试以验证测试是否失败:False

$ py test_palindrome.py
F
======================================================================
FAIL: test_palindrome (__main__.MyPalindrome.test_palindrome)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "\test_palindrome.py", line 6, in test_palindrome
    self.assertTrue (PalindromTest("civic"), "civic should be a palindrome")
AssertionError: False is not true : civic should be a palindrome

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (failures=1)

这是一个重要的检查点,用于验证您是否确实编写了正确的测试。只有这样,您才能进行最简单的编辑以通过测试:

def PalindromTest(string):
    return True

这通过了测试:

$ py test_palindrome.py
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

由于显然不是完整的实现,这告诉您需要更多的测试。例如,您可以添加以下测试:return True

def test_civil (self):
    self.assertFalse (PalindromTest("civil"), "civil should not be a palindrome")

现在运行测试套件时,新测试将失败。

为了通过整个测试套件,最简单的事情是什么?

也许这个?

def PalindromTest(string):
    return string.endswith('c')

我在这里采用了 Devil's Advocate 技术,通过故意不正确的实现来通过所有测试。至少,所有测试都通过了。

你可能会争辩说,你现在将使用红-绿-重构的重构阶段来“简化”代码:

def PalindromTest(string):
    return string == string[::-1]

可以说这样更好。这当然看起来更正确,而且由于这是一个玩具示例,我们确实可以得出这个结论。

然而,在更复杂的情况下,我们倾向于依靠测试套件来告诉我们实现是否正确,因为通常实现代码会足够复杂,以至于错误可能会被忽视。