为Django设置TDD的正确测试

时间:2011-02-11 10:16:51

标签: django testing tdd continuous-integration bdd


我一直无视长期测试我的项目的必要性。

因此,我花了一天多时间寻找方法为我当前的应用程序实施测试,并尝试为新应用程序获取一些TDD。

我找到了许多“教程”,其中包含以下步骤:“1。安装此2.安装3.安装此4.完成!”,
但似乎没有人谈论如何构建你的测试,包括文件和代码。

没有人讨论过如何设置CI服务器,或者只是将测试与项目部署集成在一起。
很多人都提到了面料,艺术品和鼻子 - 但没有人描述他们如何与他们一起工作。

我一直在寻找的是有关如何使用测试和CI等设置正确的Rails环境的详细信息......

有没有其他人觉得Django社区缺乏这个领域,还是仅仅是我? :)

哦,还有其他人对如何做有任何建议吗?

4 个答案:

答案 0 :(得分:8)

正如我所看到的,这个问题有几个部分。

您需要的是良好的单元测试。单元测试的主要特征是它们非常快,因此它们可以测试功能输入和分支覆盖的组合可能性。为了获得速度并保持测试之间的隔离,即使它们并行运行,单元测试也不应触及数据库或网络或文件系统。这些测试很难在Django项目中编写,因为Django ORM可以方便地在整个产品代码中分散数据库访问调用。因此,Django代码的任何测试都将不可避免地进入数据库。理想情况下,您应该通过将产品代码中的数据库访问限制为在django ORM之上构建的瘦数据访问层来实现此目的,该层将公开与您的应用程序相关的方法。另一种方法是让您的测试模拟出ORM调用。在最糟糕的情况下,您将放弃这一点:您的单元测试成为集成测试:它们实际上是访问数据库,跨越您的架构的多个层次,并且需要几分钟才能运行,这阻碍了开发人员经常运行它们。

这意味着编写集成测试很容易 - Django测试的规范风格完美地涵盖了这一点。

问题的最后也是最困难的部分是运行验收测试。验收测试的定义特征是,它们会像用户在生产中那样端到端地调用您的应用程序,以证明您的应用程序确实有效。使用django testrunner的Canonical dhango测试没有达到这一点。它们不会发出实际的HTTP请求(相反,它们会检查url配置,以确定将调用哪些中间件和视图来处理特定请求,然后在进程中调用它。)这意味着此类测试不会测试您的webserver配置,也没有任何javascript,或在浏览器中呈现等。要测试它,你需要像selenium这样的东西。

此外,我们有许多服务器端进程,例如cron作业,它们使用我们Django项目中的代码。涉及这些过程的验收测试应该像cron一样调用作业,作为一个新过程。

这两种情况都存在一些问题。首先,你不能简单地在Django测试运行器下运行这样的测试。如果您尝试这样做,那么您会发现在测试设置期间编写的测试数据(使用django fixtures机制,或者在测试中简单地调用“MyModel()。save()”)您的产品代码在不同的进程中运行的交易不是参与者。因此,您的测试必须在产品代码可以看到之前提交他们所做的更改。这会干扰Django的testrunner帮助完成的测试之间的清理,所以你必须将它切换到一个不同的模式,它会显式删除而不是回滚。可悲的是,这要慢得多。在昨晚的伦敦Django用户组中,一些Django核心开发人员向我保证,这种情况也有其他复杂情况(我承认我不知道它们是什么),最好避免在不运行验收测试Django测试运行器,但创建它们作为一组完全独立的测试。

如果你这样做,那么你当前的问题是你已经失去了Django测试运行器提供的好处:即它创建了一个测试数据库,并在每次测试之间进行清理。您必须为自己创建一些等效的机制。如果作为测试的一部分调用,您将需要针对测试数据库运行产品代码。您需要绝对确定,如果产品代码作为测试的一部分运行,即使在生产盒上,那么它也不会偶然触及生产数据库,因此这种机制必须绝对安全。例如,忘记在测试设置中设置环境变量不应该导致这方面的blooper。

这就是在考虑部署引起的复杂情况之前,将项目的一部分放在不同的存储库中,相互依赖,创建可以安装pip的软件包等等。

总而言之,我很想听到那些觉得他们找到了解决这个问题的好方法的人。正如一些评论者暗示的那样,这远非一个微不足道的问题。

答案 1 :(得分:5)

Harry Percival正在创建一个Django / TDD / Selenium教程(以及随后的研讨会,如果你住在伦敦。)他的书就像一本动手教程,并详细介绍了这个主题:

https://www.obeythetestinggoat.com/book/part1.harry.html

答案 2 :(得分:3)

根据我的经验,Web应用程序的细粒度单元测试不值得,设置/拆卸太昂贵且测试太脆弱了。唯一的例外是隔离组件,尤其是具有清晰输入和组件的组件。输出和复杂的算法。对这些细节进行单元测试。

我使用名为testbrowser的半功能测试工具获得了最佳测试经验,该工具模拟了Python中的浏览器操作。要与Django集成,请安装homophony应用程序(免责声明:我是应用程序的作者)。

测试浏览器对于测试驱动开发可能有点过于粗糙,但它是迄今为止我使用过的最好的测试工具。最重要的是,它可以很好地扩展,而单元测试和基于浏览器的功能测试工具随着应用程序的增长而变得非常脆弱。

对于CI工具,请使用Buildbot或Jenkins。

答案 3 :(得分:0)

我使用了python unittest框架的Django excellent extension来测试api / models / helper函数,以及在浏览器测试中使用selenium。 Selenium有很好的指导如何在python中设置和编写测试。