在测试

时间:2015-09-03 20:17:52

标签: django django-rest-framework pytest

我正在使用Django 1.8.4和DRF 3.2.1当我对指定的URL运行请求时一切正常,但是当我使用py.test运行测试时,函数更新不会进入task_id PARAM。但网址很好。

附上一些来自urls.py和views.py以及tests.py的代码..这是代码的摘录,当然很多东西都丢失了我只需要眼睛就能看出我做错了什么。

urls.py

from django.conf import settings
from django.conf.urls import include, patterns, url
from rest_framework import routers

from remotetask import views as rt_views

remotetask_detail = rt_views.RemoteTaskViewSet.as_view({'list': 'detail',
                                                       'put': 'update'})
remotetask_all = rt_views.RemoteTaskViewSet.as_view({'list': 'list'})

urlpatterns = patterns(
    '',
    url(r'^remotetasks/$', remotetask_all, name='api-remotetask-all'),
    url(r'^remotetasks/(?P<task_id>\d+)/$', remotetask_detail,
        name='api-remotetask-detail'),
    url(r'^api-auth/', include('rest_framework.urls',
                               namespace='rest_framework')),
)

views.py

from django.shortcuts import get_object_or_404

from rest_framework import generics
from rest_framework import status
from rest_framework.response import Response

from remotetask.models import RemoteTask                                                                                                        
from remotetask.serializers import RemoteTaskSerializer

来自rest_framework导入视图集

class RemoteTaskViewSet(viewsets.ViewSet):                                                                                        
    queryset = RemoteTask.objects.all()                                                                                                         
    serializer_class = RemoteTaskSerializer                                                                                                     

    def detail(self, request, task_id=None):
        task = get_object_or_404(RemoteTask, pk=task_id)
        serializer = RemoteTaskSerializer(task)

        return Response(serializer.data)


    def update(self, request, task_id=None):
        task = get_object_or_404(RemoteTask, pk=task_id)
        new_status = request.data.get('status')

        status_changed = task.change_status(new_status, stdout, stderr)

        if status_changed:
            response_status = status.HTTP_201_CREATED
        else:
            response_status = status.HTTP_400_BAD_REQUEST

        serializer = RemoteTaskSerializer(task)

        return Response(serializer.data, status=response_status)

最后是test_views.py

import pytest

from django.core.urlresolvers import reverse

from remotetask.factories import RemoteTaskFactory
from remotetask.models import RemoteTask
from remotetask.views import RemoteTaskViewSet

import json

@pytest.fixture()
@pytest.mark.django_db
def create_remotetask():
    remotetask = RemoteTaskFactory.create()
    return remotetask

@pytest.fixture()
@pytest.mark.django_db()
def clean_remotetask():
    RemoteTask.objects.all().delete()


@pytest.fixture()
def rq_remotetasklist(rf):
    url = reverse('api-remotetask-all')
    request = rf.get(url)
    response = RemoteTaskViewSet.as_view({'list': 'list'})(request)
    return response

@pytest.mark.usefixtures('clean_remotetask', 'create_remotetask')
@pytest.mark.django_db
def test_remotetask_changestatus(rq_remotetasklist, rf):
    response = rq_remotetasklist
    result = response.data.get('results')
    id_to_work = result[0]['id']
    rt = RemoteTask.objects.get(pk=id_to_work)
    assert rt.status == 0
    # new request
    url = reverse('api-remotetask-detail', kwargs={'task_id':id_to_work})
    params = json.dumps({'status': 2, 'stdout': 'test', 'stderr': 'ok'})

    request = rf.put(url, data=params,
                     content_type='application/json')

    new_response = RemoteTaskViewSet.as_view({'put': 'update'})(request)

    assert new_response.status_code == 200

默认情况下,当创建一个新任务时,它获得状态0,所以我尝试将状态更改为2并且它失败,进行一些调试我发现它正在RemoteTaskViewSet上的更新函数中输入但没有获得task_id。

我已经关注了很多教程并且来回更改了代码并且仍然遇到了相同的问题,幸运的是在生产中工作但是我担心我无法通过此代码运行测试用例。

py.test的错误输出是:

E       assert 404 == 200
E        +  where 404 = <rest_framework.response.Response object at 0x7f9f465ae690>.status_code

我把一个调试器放到更新函数中,似乎task_id是None,但是当我打印request.stream时,url是/api/remotetasks/1/ 1应该是task_id但是没有得到它,我是关于在djangoproject上打开一张票,但我认为它不是django bug,因为它适用于外部客户端,这必须是我的代码或其他任何东西。

更新:如果我使用client代替rf并使用方法调用注释我指定new_response的行,并直接验证反对request.status_code它可以正常工作!! !

这样的事情:

@pytest.mark.usefixtures('clean_remotetask', 'create_remotetask')
@pytest.mark.django_db
def test_remotetask_changestatus(rq_remotetasklist, client):
    response = rq_remotetasklist
    result = response.data.get('results')
    id_to_work = result[0]['id']
    rt = RemoteTask.objects.get(pk=id_to_work)
    assert rt.status == 0
    # new request
    url = reverse('api-remotetask-detail', kwargs={'task_id': id_to_work})
    params = json.dumps({'status': 2, 'stdout': 'test', 'stderr': 'ok'})

    request = client.put(url, data=params,
                         content_type='application/json')

    assert request.status_code == 201

现在怀疑的是它为什么不能以前一种方式工作?

1 个答案:

答案 0 :(得分:1)

问题(如更新中所述)位于request作业中:

request = rf.put(url, data=params,
                 content_type='application/json')

new_response = RemoteTaskViewSet.as_view({'put': 'update'})(request)

assert new_response.status_code == 200

确实没有必要对视图进行自定义调用。这已经由请求分配完成了。它没有在旧测试中工作,因为当它通过url路由路由时,视频不会被调用。

最重要的是,在以前的代码中,request对象不是请求,它是调用的response。使用旧代码我相信这也会有效:

@pytest.mark.usefixtures('clean_remotetask', 'create_remotetask')
@pytest.mark.django_db
def test_remotetask_changestatus(rq_remotetasklist, rf):
    response = rq_remotetasklist
    result = response.data.get('results')
    id_to_work = result[0]['id']
    rt = RemoteTask.objects.get(pk=id_to_work)
    assert rt.status == 0
    # new request
    url = reverse('api-remotetask-detail', kwargs={'task_id':id_to_work})
    params = json.dumps({'status': 2, 'stdout': 'test', 'stderr': 'ok'})

    response = rf.put(url, data=params,
                     content_type='application/json')

    assert response.status_code == 200