Sto utilizzando Django 1.8.4 e DRF 3.2.1 e quando eseguo richieste contro gli URL specificati tutto funziona correttamente, ma quando eseguo i test con py. testare l'aggiornamento della funzione non entra con il parametro task_id. Ma l'url va bene.Django o Django Rest Framework non può risolvere il parametro url durante il test
In allegato un codice da urls.py e views.py e tests.py .. questo è un estratto del codice, ovviamente manca un sacco di cose Ho solo bisogno di occhi che possano vedere se sto facendo qualcosa di sbagliato.
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
da rest_framework viewsets importazione
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)
E infine 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
Per impostazione predefinita, quando viene creata una nuova attività, ottiene lo stato 0, quindi provo a cambiare lo stato su 2 e non riesce, eseguendo un po 'di debug che ho trovato che sta entrando nella funzione di aggiornamento su RemoteTaskViewSet ma non sta ottenendo il task_id.
Ho seguito un sacco di esercitazioni e ho cambiato il codice e continuo ad avere lo stesso problema, fortunatamente funziona in produzione ma mi preoccupa che non riesco a farlo eseguire test case da questo codice.
L'uscita di errore da py.test è questo:
E assert 404 == 200
E + where 404 = <rest_framework.response.Response object at 0x7f9f465ae690>.status_code
ho messo un debugger nella funzione di aggiornamento, sembra che task_id è Nessuno, ma quando stampo request.stream l'URL è /api/remotetasks/1/
1 dovrebbe essere il task_id ma non lo capisce, stavo per aprire un ticket su djangoproject ma penso che non sia un bug django visto che funziona con client esterni, questo deve essere qualcosa sul mio codice, o qualsiasi altra cosa.
Aggiornamento: Se uso client
invece rf
e commentare la linea dove assegno new_response
con la chiamata del metodo, e convalidare direttamente l'request.status_code contro di esso funziona !!!.
Qualcosa di simile a questo:
@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
Ora il dubbio è il motivo per cui non funziona nel modo precedente?
Cosa succede se si rimuovono tutti i test diversi da quello che non riesce? Se si inserisce una dichiarazione pdb e si ispeziona l'oggetto risposta cosa ha? Anche perché il {'put': 'update'} nella chiamata as view? –
Nell'esempio c'è solo un test, l'ho fatto e il test continua a fallire. Intendi la new_response che ha un oggetto rest_framewor.response.Response. Perché l'aggiornamento messo? .. beh questo è un materiale DRF di cui ho bisogno dal momento che RemoteTaskViewSet è figlio di viewset.ViewSet –