简体   繁体   English

在python中模拟用户输入以进行测试

[英]Emulating user input in python for testing

I have written a simple python program that takes user input, with the use of input(). 我编写了一个简单的python程序,它使用input()来获取用户输入。 There are some different commands available. 有一些不同的命令可用。

I want to make sure that all available commands function as intended and that the program catches invalid commands. 我想确保所有可用命令按预期运行,并且程序捕获无效命令。 Since there are quite a few different commands, this is very time-consuming to do manually (ie, start the program, and enter all commands, one by one). 由于存在相当多的不同命令,因此手动执行(即启动程序并逐个输入所有命令)非常耗时。 (I have separate test functions for the actual execution of all commands, but I'm struggling to find a nice way to test this functionality together with the input() loop.) (我对所有命令的实际执行都有单独的测试函数,但是我很难找到一种与input()循环一起测试这个功能的好方法。)

How can I automate the process of giving (predetermined) user inputs, without messing up the rest of the code? 如何在不弄乱其余代码的情况下自动执行(预定)用户输入的过程? In addition to using this to test the program, it would also serve as an example to the user, in order to see the possible usage of the program. 除了使用它来测试程序之外,它还可以作为用户的示例,以便查看程序的可能用法。

My current solution is that I have two versions of the main() function, which is basically just an infinite loop that takes inputs until an exit command is given. 我目前的解决方案是我有两个版本的main()函数,它基本上只是一个无限循环,它接受输入直到给出一个退出命令。 The first version, "main()", is the version intended for use and takes inputs from input(), until the user decides to quit. 第一个版本“main()”是打算使用的版本,并从input()获取输入,直到用户决定退出。 The second version, "main_test()" is only used for testing, and takes the inputs from a predetermined list, specified in the code. 第二个版本“main_test()”仅用于测试,并从代码中指定的预定列表中获取输入。 This does the job, but I do not want the main_test() code in the final version. 这样做,但我不想在最终版本中使用main_test()代码。 I also do not want to "pollute" main() by adding things only used for testing. 我也不想通过添加仅用于测试的东西来“污染”main()。

def main():
    while True:
        user_input = input()
        ...
def main_test():
    test_input = [...]
    test_iter = 0
    while True:
        user_input = test_input[test_iter]
        test_iter += 1
        ...

I have not been able to find a nice way to do this in python, although I'm sure there must be a smart way. 我无法在python中找到一个很好的方法,虽然我确信必须有一个聪明的方法。 I'd prefer a way that does not need any additional imports. 我更喜欢一种不需要任何额外进口的方式。 But if there is a nice way to do it with additional imports, I'm all ears. 但是,如果有一个很好的方法来做额外的进口,我都是耳朵。

Anyway, striking out with python, my next thought was to specify the commands in a Makefile, where I would start the program and feed the program text input, emulating the user. 无论如何,使用python,我的下一个想法是在Makefile中指定命令,在那里我将启动程序并提供程序文本输入,模拟用户。 The main benefit of this is that I would only need the "main()" function, and I would not have to change anything in the python code. 这样做的主要好处是我只需要“main()”函数,而且我不需要在python代码中更改任何内容。 The disadvantage is that the example/test is specified outside of the *.py files, which may confuse the user. 缺点是示例/测试是在* .py文件之外指定的,这可能会使用户感到困惑。

If you are looking to confirm that X input results in Y output, then what you are looking for is called unit testing ; 如果你想确认X输入结果是Y输出,那么你要找的是单元测试 ; this methodology allows you to define functions that assess the result of your function against your expected results. 此方法允许您定义根据预期结果评估函数结果的函数。

Module options: 模块选项:
- pytest - pytest
- unittest - unittest

First of all, I would like to point out that there are many methods for testing your code and some are better practice than others, while each one can be preferred by the programmer for different reasons. 首先,我想指出有很多方法可以测试你的代码,有些方法比其他方法更好,而程序员可能会因为不同的原因而倾向于每个方法。 You should study how to test your code using the existing ways. 您应该学习如何使用现有方法测试代码。 Depending on the structure of your code, patterns that can be exploited, and your implementation principles that you follow (dependency injections, mvc, mvvm, etc). 取决于代码的结构,可以利用的模式,以及您遵循的实现原则(依赖注入,mvc,mvvm等)。

As for your specific case, I would recommend to unittest your fraction of the code that uses the user input and define a collection of cases with predefined outputs that your can assert. 至于您的具体情况,我建议您对使用用户输入的代码部分进行单元测试,并定义一组具有您可以断言的预定义输出的案例。 Then, use the same code (maybe add cases) whenever you edit this fraction, in order to be sure that your program continues to work fluently. 然后,每当编辑此分数时,使用相同的代码(可能添加案例),以确保您的程序继续流畅地工作。

Using Python's Unittest package you can implement a nice script that checks your code consistently and incorporate it to your project. 使用Python的Unittest包,您可以实现一个很好的脚本,可以一致地检查您的代码并将其合并到您的项目中。 See also Wikipedia page about unit testing to learn more about the principles you have to follow. 另请参阅有关单元测试的 Wikipedia页面,以了解有关您必须遵循的原则的更多信息。 You can also check Tensorflow's testing page for directions on how to incorporate this kind of testing in a bigger project, and use these ideas in yours. 您还可以查看Tensorflow的测试页面 ,了解如何在更大的项目中加入此类测试,并在您的测试中使用这些想法。

Good luck! 祝好运!

The answer from here should work if you don't mind importing unittest, python mocking raw input in unittests . 如果您不介意在unittests中导入unittest, python mocking raw输入,那么这里的答案应该有效。

The main_test() part can then be removed from you projects and taken care of in the testing script. 然后可以从您的项目中删除main_test()部分并在测试脚本中处理。 The "return_values" then correspond to you mock inputs. 然后“return_values”对应于模拟输入。

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

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