Translating 20%:

This commit is contained in:
cposture 2016-07-30 22:09:51 +08:00
parent 3fa6545a9a
commit e0a9969aac

View File

@ -1,34 +1,36 @@
Translating by cposture 2016-07-29
An Introduction to Mocking in Python
Mock 在 Python 中的使用介绍
=====================================
http://www.oschina.net/translate/an-introduction-to-mocking-in-python?cmp
本文讲述的是 Python 中 Mock 的使用
This article is about mocking in python,
**如何在避免测试你的耐心的情景下执行单元测试**
**How to Run Unit Tests Without Testing Your Patience**
通常,我们编写的软件会直接与我们称之为肮脏无比的服务交互。用外行人的话说:交互已设计好的服务对我们的应用程序很重要,但是这会带来我们不希望的副作用,也就是那些在我们自己测试的时候不希望的功能。例如:我们正在写一个社交 app并且想要测试一下我们 "发布到 Facebook" 的新功能,但是不想每次运行测试集的时候真的发布到 Facebook。
More often than not, the software we write directly interacts with what we would label as “dirty” services. In laymans terms: services that are crucial to our application, but whose interactions have intended but undesired side-effects—that is, undesired in the context of an autonomous test run.For example: perhaps were writing a social app and want to test out our new Post to Facebook feature, but dont want to actually post to Facebook every time we run our test suite.
The Python unittest library includes a subpackage named unittest.mock—or if you declare it as a dependency, simply mock—which provides extremely powerful and useful means by which to mock and stub out these undesired side-effects.
Python 的单元测试库包含了一个名为 unittest.mock 或者可以称之为依赖的子包,简言之为 mock——其提供了极其强大和有用的方法通过它们可以模拟和打桩我们不希望的副作用。
>Source | <http://www.toptal.com/python/an-introduction-to-mocking-in-python>
Note: mock is [newly included][1] in the standard library as of Python 3.3; prior distributions will have to use the Mock library downloadable via [PyPI][2].
注意mock [最近收录][1]到了 Python 3.3 的标准库中;先前发布的版本必须通过 [PyPI][2] 下载 Mock 库。
###
### Fear System Calls
To give you another example, and one that well run with for the rest of the article, consider system calls. Its not difficult to see that these are prime candidates for mocking: whether youre writing a script to eject a CD drive, a web server which removes antiquated cache files from /tmp, or a socket server which binds to a TCP port, these calls all feature undesired side-effects in the context of your unit-tests.
再举另一个例子,思考一个我们会在余文讨论的系统调用。不难发现,这些系统调用都是主要的模拟对象:无论你是正在写一个可以弹出 CD 驱动的脚本,还是一个用来删除 /tmp 下过期的缓存文件的 Web 服务,这些调用都是在你的单元测试上下文中不希望的副作用。
>As a developer, you care more that your library successfully called the system function for ejecting a CD as opposed to experiencing your CD tray open every time a test is run.
> 作为一个开发者,你需要更关心你的库是否成功地调用了一个可以弹出 CD 的系统函数,而不是切身经历 CD 托盘每次在测试执行的时候都打开了。
As a developer, you care more that your library successfully called the system function for ejecting a CD (with the correct arguments, etc.) as opposed to actually experiencing your CD tray open every time a test is run. (Or worse, multiple times, as multiple tests reference the eject code during a single unit-test run!)
作为一个开发者,你需要更关心你的库是否成功地调用了一个可以弹出 CD 的系统函数(使用了正确的参数等等),而不是切身经历 CD 托盘每次在测试执行的时候都打开了。(或者更糟糕的是,很多次,在一个单元测试运行期间多个测试都引用了弹出代码!)
Likewise, keeping your unit-tests efficient and performant means keeping as much “slow code” out of the automated test runs, namely filesystem and network access.
同样,保持你的单元测试的效率和性能意味着需要让如此多的 "缓慢代码" 远离自动测试,比如文件系统和网络访问。
For our first example, well refactor a standard Python test case from original form to one using mock. Well demonstrate how writing a test case with mocks will make our tests smarter, faster, and able to reveal more about how the software works.
对于我们首个例子,我们要从原始形式到使用 mock 地重构一个标准 Python 测试用例。我们会演示如何使用 mock 写一个测试用例使我们的测试更加智能、快速,并且能展示更多关于我们软件的工作原理。
### A Simple Delete Function
### 一个简单的删除函数
We all need to delete files from our filesystem from time to time, so lets write a function in Python which will make it a bit easier for our scripts to do so.
有时,我们都需要从文件系统中删除文件,因此,让我们在 Python 中写一个可以使我们的脚本更加轻易完成此功能的函数。
```
#!/usr/bin/env python
@ -40,9 +42,9 @@ def rm(filename):
os.remove(filename)
```
Obviously, our rm method at this point in time doesnt provide much more than the underlying os.remove method, but our codebase will improve, allowing us to add more functionality here.
很明显,我们的 rm 方法此时无法提供比相关 os.remove 方法更多的功能,但我们的基础代码会逐步改善,允许我们在这里添加更多的功能。
Lets write a traditional test case, i.e., without mocks:
让我们写一个传统的测试用例,即,没有使用 mock
```
#!/usr/bin/env python
@ -69,9 +71,11 @@ class RmTestCase(unittest.TestCase):
self.assertFalse(os.path.isfile(self.tmpfilepath), "Failed to remove the file.")
```
Our test case is pretty simple, but every time it is run, a temporary file is created and then deleted. Additionally, we have no way of testing whether our rm method properly passes the argument down to the os.remove call. We can assume that it does based on the test above, but much is left to be desired.
我们的测试用例相当简单,但是当它每次运行的时候,它都会创建一个临时文件并且随后删除。此外,我们没有办法测试我们的 rm 方法是否正确地将我们的参数向下传递给 os.remove 调用。我们可以基于以上的测试认为它做到了,但还有很多需要改进的地方。
Refactoring with MocksLets refactor our test case using mock:
### 使用 Mock 重构
让我们使用 mock 重构我们的测试用例:
```
#!/usr/bin/env python
@ -91,10 +95,11 @@ class RmTestCase(unittest.TestCase):
mock_os.remove.assert_called_with("any path")
```
With these refactors, we have fundamentally changed the way that the test operates. Now, we have an insider, an object we can use to verify the functionality of another.
使用这些重构,我们从根本上改变了该测试用例的运行方式。现在,我们有一个可以用于验证其他功能的内部对象。
### Potential Pitfalls
### 潜在陷阱
第一件需要注意的事情就是,我们使用了用于模拟 mock.patch 方法的装饰器位于mymodule.os
One of the first things that should stick out is that were using the mock.patch method decorator to mock an object located at mymodule.os, and injecting that mock into our test case method. Wouldnt it make more sense to just mock os itself, rather than the reference to it at mymodule.os?
Well, Python is somewhat of a sneaky snake when it comes to imports and managing modules. At runtime, the mymodule module has its own os which is imported into its own local scope in the module. Thus, if we mock os, we wont see the effects of the mock in the mymodule module.
@ -480,12 +485,3 @@ via: http://slviki.com/index.php/2016/06/18/introduction-to-mocking-in-python/
[6]: http://www.voidspace.org.uk/python/mock/mock.html
[7]: http://www.toptal.com/qa/how-to-write-testable-code-and-why-it-matters
[8]: http://www.toptal.com/python