6

我有兴趣学习如何以更敏捷 / 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 正常工作。实际的服务器根本不返回任何产品。

4

4 回答 4

3

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

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

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

我认为您想从各自的模块和功能中获取文档测试并在单元测试框架中执行它们。这将负责测试数据设置/拆卸。如果您的文档测试是从 Django 的 unittest.TestCase 子类的测试方法中执行的,那么他们将能够使用该测试数据库。您还可以将模拟请求对象传递到文档测试的执行上下文中。这是一个Django 片段,它提供了一个模拟请求对象和它的信息。假设您想测试所有应用程序视图中的文档字符串。你可以在 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})

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

于 2009-12-16T20:48:07.577 回答
1

你的观点的写法,很难测试。您必须抓取 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”。

于 2009-12-15T14:46:02.813 回答
1

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

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

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

于 2010-01-07T06:02:07.700 回答
0

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

于 2009-12-15T14:33:34.897 回答