我正在为使用外部数据源的 Django 应用程序编写测试。显然,我使用假数据来测试我的类的所有内部工作,但我也想对实际的获取器进行一些测试。其中之一将需要验证外部源是否仍在以我的应用程序期望的格式发送数据,这意味着在测试中发出检索该信息的请求。
显然,我不希望我们的 CI 在出现网络问题或数据提供商出现故障时停机。在这种情况下,我想发出一个警告,跳过该测试方法的其余部分,并且不会导致整体失败。这样,如果数据成功到达,我可以检查它的一致性(如果存在问题,则失败),但如果无法获取数据,它会记录一条警告,以便我(或其他开发人员)知道快速检查数据源是否正常。
基本上,我想测试我的外部源而不依赖它!
Django的测试套件使用Python的unittest模块(至少,这就是我使用它的方式),考虑到文档,它看起来很有用因为它描述了跳过测试和预期失败 。这个功能显然是“2.7 版中的新功能”,这解释了为什么我无法让它工作 - 我已经从控制台检查了我安装的unittest 版本,它似乎是1.63!
我在 pypi 中找不到更高版本的unittest,所以我想知道在哪里可以获取 该文档以及它是否适用于 Django (1.2)。
我显然愿意接受以下建议/讨论:这是否是解决我的问题的最佳方法:)
[编辑 - 附加信息/澄清]
正如我所说,我显然是在嘲笑依赖性并对此进行测试。但是,我还希望能够检查外部资源(通常是 API)是否仍然符合我的预期格式,而不会在出现网络问题或服务器暂时关闭时关闭 CI。我基本上只是想检查资源的一致性。
考虑以下情况...
如果您编写了 Twitter 应用程序,您将对应用程序的所有方法和行为进行测试 - 这些将使用虚假的 Twitter 数据。这为您的应用程序提供了一套完整、独立的测试。问题是,这实际上并没有检查应用程序是否正常工作,因为您的应用程序本质上依赖于 Twitter API 的一致性。如果 Twitter 更改 API 调用(可能更改 URL、参数或响应),应用程序将停止工作,即使单元测试仍会通过。 (或者也许他们要完全关闭基本身份验证!)
我的用例更简单 - 我有一个用于导入信息的单个 xml 资源。我伪造了该资源并测试了我的导入代码,但我想进行一个测试来检查该 xml 资源的格式是否未更改。
我的问题是关于跳过 Django 测试运行器中的测试,这样如果资源不可用,我可以在测试失败的情况下发出警告,特别是获取支持此行为的 Python 单元测试模块版本。我提供了这么多背景信息,以便任何在该领域有经验的人都可以提供替代建议。
对于这个冗长的问题,我深表歉意,我知道大多数人现在不会阅读此内容。
我将重要的部分“加粗”,以使其更易于阅读。
I'm writing tests for a Django application that uses an external data source. Obviously, I'm using fake data to test all the inner workings of my class but I'd like to have a couple of tests for the actual fetcher as well. One of these will need to verify that the external source is still sending the data in the format my application expects, which will mean making the request to retrieve that information in the test.
Obviously, I don't want our CI to come down when there is a network problem or the data provider has a spot of downtime. In this case, I would like to throw a warning that skips the rest of that test method and doesn't contribute to an overall failure. This way, if the data arrives successfully I can check it for consistency (failing if there is a problem) but if the data cannot be fetched it logs a warning so I (or another developer) know to quickly check that the data source is ok.
Basically, I would like to test my external source without being dependant on it!
Django's test suite uses Python's unittest module (at least, that's how I'm using it) which looks useful, given that the documentation for it describes Skipping tests and expected failures. This feature is apparently 'new in version 2.7', which explains why I can't get it to work - I've checked the version of unittest I have installed on from the console and it appears to be 1.63!
I can't find a later version of unittest in pypi so I'm wondering where I can get hold of the unittest version described in that document and whether it will work with Django (1.2).
I'm obviously open to recommendations / discussion on whether or not this is the best approach to my problem :)
[EDIT - additional information / clarification]
As I said, I'm obviously mocking the dependancy and doing my tests on that. However, I would also like to be able to check that the external resource (which typically is going to be an API) still matches my expected format, without bringing down CI if there is a network problem or their server is temporarily down. I basically just want to check the consistency of the resource.
Consider the following case...
If you have written a Twitter application, you will have tests for all your application's methods and behaviours - these will use fake Twitter data. This gives you a complete, self-contained set of tests for your application. The problem is that this doesn't actually check that the application works because your application inherently depends on the consistency of Twitter's API. If Twitter were to change an API call (perhaps change the URL, the parameters or the response) the application would stop working even though the unit tests would still pass. (Or perhaps if they were to completely switch off basic authentication!)
My use case is simpler - I have a single xml resource that is used to import information. I have faked the resource and tested my import code but I would like to have a test that checks the format of that xml resource has not changed.
My question is about skipping tests in Django's test runner so I can throw a warning if the resource is unavailable without the tests failing, specifically getting a version of Python's unittest module that supports this behaviour. I've given this much background information to allow anyone with experience in this area to offer alternative suggestions.
Apologies for the lengthy question, I'm aware most people won't read this now.
I've 'bolded' the important bits to make it easier to read.
发布评论
评论(3)
由于您的编辑使我的上一个答案无效,我创建了一个单独的答案。
我假设您正在 Python 版本 2.6 上运行 - 我相信您在单元测试中寻找的更改可以在 Python 版本 2.7 中找到。由于 unittest 位于标准库中,因此更新到 Python 2.7 应该可以让您使用这些更改。这是一个适合您的选择吗?
我可能建议的另一件事是将“外部源格式验证”测试分离到一个单独的测试套件中,并与其余的单元测试分开运行。这样,您的核心单元测试仍然很快,并且您不必担心外部依赖项会破坏您的主要测试套件。如果您使用 Hudson,那么创建一个单独的作业来为您处理这些测试应该相当容易。只是一个建议。
I created a separate answer since your edit invalidated my last answer.
I assume you're running on Python version 2.6 - I believe the changes that you're looking for in unittest are available in Python version 2.7. Since unittest is in the standard library, updating to Python 2.7 should make those changes available to you. Is that an option that will work for you?
One other thing that I might suggest is to maybe separate the "external source format verification" test(s) into a separate test suite and run that separately from the rest of your unit tests. That way your core unit tests are still fast and you don't have to worry about the external dependencies breaking your main test suites. If you're using Hudson, it should be fairly easy to create a separate job that will handle those tests for you. Just a suggestion.
2.7 中unittest 中的新功能已作为unittest2 向后移植到2.6。您只需 pip install 并用unittest2 替换unittest,您的测试将像您一样工作,而且您无需升级到2.7 即可获得新功能。
The new features in unittest in 2.7 have been backported to 2.6 as unittest2. You can just pip install and substitute unittest2 for unittest and your tests will work as thyey did plus you get the new features without upgrading to 2.7.
你想测试什么?您的 Django 应用程序或依赖项中的代码?你可以模拟任何外部依赖吗?如果您只想测试您的 Django 应用程序,那么我会说模拟外部依赖项,这样您的测试就不会依赖于该外部资源的可用性。
如果您可以发布“实际获取器”的一些代码,也许您会得到一些有关如何使用模拟的提示。
What are you trying to test? The code in your Django application(s) or the dependency? Can you just Mock whatever that external dependency is? If you're just wanting to test your Django application, then I would say Mock the external dependency, so your tests are not dependent upon that external resource's availability.
If you can post some code of your "actual fetcher" maybe you will get some tips on how you could use mocks.