如何向 Python 单元测试提供标准输入、文件和环境变量输入?
如何在出现以下情况时编写测试:
- 测试用户输入。
- 测试从文件读取的输入。
- 测试从环境变量读取的输入。
如果有人能告诉我如何处理上述场景,那就太好了;如果您能给我指出一些我可以的文档/文章/博客文章,那就太棒了 读。
How to write tests where conditions like the following arise:
- Test user Input.
- Test input read from a file.
- Test input read from an environment variable.
It'd be great if someone could show me how to approach the above mentioned scenarios; it'd still be awesome if you could point me to a few docs/articles/blog posts which I could
read.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您所描述的所有三种情况都是您需要特别注意的地方,以确保您在设计中使用松耦合。
您真的需要对Python的
raw_input
方法进行单元测试吗?open
方法? os.environ.get?不可以。您需要设置您的设计,以便可以替代检索该输入的其他方式。然后,在单元测试期间,您将放入某种实际上并不调用
raw_input
或open
的存根。例如,您的正常代码可能类似于:
会话如下:
那么您的测试将类似于:
请记住,您不必测试语言的 IO 设施(除非您是设计该语言的人,即完全不同的情况)。
All three situations you've described are where you need to specifically go out of your way to ensure you are using loose coupling in your design.
Do you really need to unit test Python's
raw_input
method? Theopen
method?os.environ.get
? No.You need to set up your design so that you can substitute other ways of retrieving that input. Then, during your unit tests, you'll throw in a stub of some sort that doesn't actually call
raw_input
oropen
.For instance, your normal code might be something like:
The session looks like:
Then your test will be like:
Keep in mind that you should not have to test a language's IO facilities (unless you're the one designing the language, which is a different situation entirely).
如果您依赖于使用 raw_input (或任何其他特定输入源),我是 的大力支持者模拟库。鉴于 Mark Rushakoff 在他的示例中使用的代码:
您的测试代码可以使用模拟:
这些断言将通过。请注意,side_effect 按顺序返回列表的元素。它还能做更多事情!我建议查看文档。
If you are tied to using raw_input (or any other specific input source), I'm a big proponent of the mock library. Given the code that Mark Rushakoff used in his example:
Your test code could use mock:
These assertions would pass. Note that side_effect returns the elements of the list in order. It can do so much more! I'd recommend checking out the documentation.
如果您可以在不使用外部流程的情况下摆脱困境,那就这样做。
然而,在某些情况下,这很复杂,并且您确实想要使用进程,例如,您想要测试 C 可执行文件的命令行界面。
用户输入
使用
subprocess.Popen
,如下所示:从用户获取输入和从管道获取输入以使用
raw_input<等方法完成输入没有区别/code> 或
sys.stdin.read()
。文件
创建一个临时目录并在测试
setUp
方法中创建您想要从中读取的文件:在测试中读取文件。
之后删除临时目录。
从文件中读取数据是相当复杂的,大多数程序可以从文件中读取,也可以从 STDIN 中读取(例如使用
fileinput
)。所以,如果你想测试的是输入特定内容时会发生什么,并且你的程序接受STDIN,只需使用Popen
来测试程序。环境变量
os.environ["THE_VAR"] = "the_val"
设置环境变量,del os.environ["THE_VAR"]
取消设置code>os.environ = {'a':'b'}
不起作用subprocess.Popen
。环境是从调用进程继承的。模板代码
我在我的github上有一个模块< /a> 测试
STDOUT
、STDERR
以及给定STDIN
的退出状态、命令行参数和环境。另外,检查“tests”目录下该模块的测试。一定有更好的模块可以实现这一点,所以我的模块只是为了学习目的。If you can get away without using an external process, do so.
However, there are situations where this is complicated, and you really want to use process, e.g., you want to test the command line interface of a C executable.
User input
Use
subprocess.Popen
as in:There is no difference between taking input from a user and taking it from a pipe for input done with methods like
raw_input
orsys.stdin.read()
.Files
Create a temporary directory and create the files you want to read from in there on your test
setUp
methods:Do the file reading in the tests.
Remove the temp dir afterwards.
It is quite complicated reading from files, and most programs can read either from files or from STDIN (e.g. with
fileinput
). So, if what you want to test is what happens when a certain content is input, and your program accepts STDIN, just usePopen
to test the program.Environment variables
os.environ["THE_VAR"] = "the_val"
del os.environ["THE_VAR"]
os.environ = {'a':'b'}
does not worksubprocess.Popen
. The environment is inherited from the calling process.Template Code
I have a module on my github that tests
STDOUT
,STDERR
and the exit status givenSTDIN
, command line arguments and enviroment. Also, check the tests for that module under the "tests" dir. There must be much better modules out there for this, so take mine just for learning purposes.使用 pytest:
Using pytest: