简体   繁体   English

Python 单元测试模块而不是 function

[英]Python unittest a module instead of a function

I'm trying to write a test.py file to test a module I wrote.我正在尝试编写一个 test.py 文件来测试我编写的模块。 The specifications of the program are that I take serial user input and then print, not return a single answer.该程序的规范是我接受串行用户输入然后打印,而不是返回单个答案。 The first line of user input indicates how many inputs will follow.用户输入的第一行表示接下来有多少输入。 With an example program, "4\n1\n2\n3\n4\n" would mean there are 4 inputs and the inputs are [1,2,3,4].对于示例程序,“4\n1\n2\n3\n4\n”表示有 4 个输入,输入为 [1,2,3,4]。 Here is an example of the program that would take the input (sumEx.py):下面是一个接受输入的程序示例 (sumEx.py):

import sys
def sum():

    n = int(sys.stdin.readline().strip())
    nums = []
    for _ in range(n):
        nums.append(int(sys.stdin.readline().strip()))

    result = 0
    for num in nums:
        result += num
    
    print(result)

if __name__ == "__main__":
    sum()

I realize that in this example the for loop is redundant, but this is just an example for the actual program I am working on to abstract the problem.我意识到在这个例子中 for 循环是多余的,但这只是我正在处理的抽象问题的实际程序的一个例子。 Currently, this is the test file I have:目前,这是我拥有的测试文件:

from io import StringIO
import sys
from _pytest.monkeypatch import MonkeyPatch
import unittest
from sumEx import sum as program

class Testing(unittest.TestCase):
    def test_string(self):
        monkeypatch = MonkeyPatch()
        monkeypatch.setattr('sys.stdin', StringIO("8\n1\n2\n3\n4\n5\n6\n7\n8\n"))
        self.assertEqual(program(), 36)

    def test_boolean(self):
        monkeypatch = MonkeyPatch()
        monkeypatch.setattr('sys.stdin', StringIO("4\0\n1\n2\n3\n"))
        self.assertEqual(program(), 6)

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

The problem is that my tests will only work if I returned them instead of printing them.问题是我的测试只有在我退回而不是打印它们时才能工作。 Ideally, my test file would call the file sumEx.py and then理想情况下,我的测试文件会调用文件 sumEx.py 然后

if __name__ == "__main__":
    sum()

would call the sum function, the test would supply the input (like an actual person typing each line), and then whatever sum prints would be considered the output for the test.将调用总和 function,测试将提供输入(就像实际输入每一行的人一样),然后任何总和打印都将被视为 output 用于测试。 Any help is greatly appreciated.任何帮助是极大的赞赏。 Please ask any questions if something is too vague.如果有些东西太模糊,请提出任何问题。 Thank you!谢谢!

If anyone is curious, this is what I'm gonna go with for now.如果有人好奇,这就是我现在要使用的 go。 This takes input from a file and mimics user input through sys.stdin.这从文件中获取输入并通过 sys.stdin 模拟用户输入。 It then reads the correct output from a file and compares it to the output of the program.然后它从文件中读取正确的 output 并将其与程序的 output 进行比较。 It also runs the same test case with different inputs with the help of parameterization.它还借助参数化运行具有不同输入的相同测试用例。 Thank you @MrBeanBremen for the suggestion!谢谢@MrBeanBremen 的建议!

class Testing(unittest.TestCase):

    def load_file(self, fileName, inOut):
        try:
            inputFile = open(fileName, 'r')
            fileInput = r'{}'.format(inputFile.readline())
            for line in inputFile.readlines():
                fileInput = r'{}'.format(fileInput + line)
            if inOut == 'in':
                fileInput = r'{}'.format(fileInput+'\n')
            inputFile.close()
            return fileInput
        except:
            print("ERROR LOADING FILE")
        
    @parameterized.expand([
        ["./tests/test0in.txt", "./tests/test0out.txt"],
        ["./tests/test1in.txt", "./tests/test1out.txt"],
        ["./tests/test2in.txt", "./tests/test2out.txt"]])
    @patch('sys.stdout', new_callable=StringIO)
    def test(self, inputFile, outputFile, mock_stdout):
        monkeypatch = MonkeyPatch()

        monkeypatch.setattr('sys.stdin', StringIO(self.load_file(inputFile, "in")))
        program.main()
        self.assertEqual(mock_stdout.getvalue(), self.load_file(outputFile, "out"))
    
if __name__ == '__main__':
    unittest.main(verbosity=2)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM