【问题标题】:Examples of using Doctests in Django in an Agile / BDD way以敏捷/BDD 方式在 Django 中使用 Doctests 的示例
【发布时间】:2009-12-15 13:51:49
【问题描述】:

我有兴趣学习如何以更敏捷/BDD 的方式进行 Doctests 和单元测试。 我发现了一些看似合理的教程,但它们只是缩略图。 我真正想看的是一些以BDD风格开发的Django项目的源代码。

我不清楚的是你如何处理请求对象等。 我有一种情况,我已经部署了我的应用程序,并且我在生产中得到了完全不同的行为,我在开发中甚至从生产服务器上的 Python shell 中得到了完全不同的行为。我希望一些 Doctests 能帮助我诊断这个问题,并为更敏捷的首先编写测试的过程打开大门。

具体来说,这是我要测试的代码:

def match_pictures_with_products( queryset, number_of_images = 3):      
    products = []  
    i = 0    
    for product in queryset:  
       if i < ( number_of_images ):  
           image =  product.imagemain_set.all()[:1]  
           product.photo_url = image[0].photo.url  

       products.append(product)  
       i += 1  

    return products  

def index(request):  
    """returns the top 10 most clicked products"""     
    products = Product.objects.all()[:10]  
    products = match_pictures_with_products( products, 10)  .  
    return render_to_response('products/product_list.html', {'products': products}) 

如何创建确保索引返回 10 个对象的 Doctest?
产品查询似乎可以从生产服务器上的 shell 正常工作。实际的服务器根本没有返回任何产品。

【问题讨论】:

  • 如果你想要一个 BDD 工具,试试 lettuce。

标签: python django agile doctest


【解决方案1】:

我以前也问过自己同样的问题。我发现 doctests 对于视图、模型方法和管理器之类的用途有限,因为

  1. 您需要能够设置和拆卸测试数据集以实际用于测试
  2. 视图需要一个请求对象。在 doctest 中,这是从哪里来的?

出于这个原因,我一直使用 Django unit testing 框架来为您处理所有这些。但不幸的是,您并没有从 doctest 中获得一些好处,这使得 TDD/BDD 更难实现。接下来是纯粹的猜测,关于您如何完成这项工作:

我认为您希望从它们各自的模块和函数中获取 doctest,并在单元测试框架中执行它们。这将负责测试数据设置/拆卸。如果您的 doctests 是从子类 Django 的 unittest.TestCase 的测试方法中执行的,他们将能够使用该测试数据库。您还可以将模拟请求对象传递到文档测试的执行上下文中。这是一个Django snippet,它提供了一个模拟请求对象和info。假设您想测试所有应用程序视图中的文档字符串。你可以在 tests.py 中做这样的事情:

from ??? import RequestFactory
from doctest import testmod, DocTestFailure
from django.test import TestCase

from myapp import views

class MyAppTest(TestCase):

    fixtures = ['test_data.json']

    def test_doctests(self):                
        try:
            testmod(views, extraglobs={
                'REQUEST': RequestFactory()
            }, raise_on_error=True)
        except DocTestFailure, e:
            self.fail(e)

这个应该允许你做这样的事情:

def index(request):  
    """
    returns the top 10 most clicked products

    >>> response = index(REQUEST)
    >>> [test response content here]

    """     
    products = Product.objects.all()[:10]  
    products = match_pictures_with_products( products, 10)  .  
    return render_to_response('products/product_list.html', {'products': products})

同样,这只是我的想法,根本没有经过测试,但这是我认为您可以在不将所有视图测试放入单元测试框架的情况下实现所需的唯一方法。

【讨论】:

    【解决方案2】:

    您的视图的编写方式很难测试。您必须抓取 html 以查看您想要的内容是否存在,然后您的测试超出了您的需要。更好的是重写您的视图以使其更易于测试。首先参数化您的模板名称,这样您就可以创建一个简单的测试模板:

    def index(request, template_name='products/product_list.html'):  
        """returns the top 10 most clicked products"""     
        products = Product.objects.all()[:10]  
        products = match_pictures_with_products( products, 10)  .  
        return render_to_response(template_name, {'products': products})
    

    然后你可以写一个简单的模板,只计算产品的数量:

    {{ products.count }} 
    

    并确保模板返回“10”。

    【讨论】:

    • 我不确定我是否在关注这个。你会用 Doctest 测试模板吗?我很想看到一些 Django 项目已经实现了。
    【解决方案3】:

    您可以使用django testclient 并测试设置的上下文变量:

    >>> response = client.get('/foo/')
    >>> response.context['name']
    'Arthur'
    

    您还可以检查响应代码以确保页面返回成功200

    【讨论】:

      【解决方案4】:

      zope.testbrowser 包可能在您的文档测试中很有用,因为您想分析生产服务器的呈现 HTML 答案。

      【讨论】:

        猜你喜欢
        • 2013-06-13
        • 1970-01-01
        • 2017-05-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多