2016-05-04 10 views
0

Ich versuche, einen Integrationstest für eine Django-Anwendung zu schreiben, um zu testen, ob das Passwort von einer Rest-API geändert wurde. Nach dem Aufruf der API für die Kennwortänderung funktioniert das Testen des neuen Kennworts jedoch nicht.Kann Passwortänderung in Django unittest nicht testen

Was ich hier mache ist: Ich habe das Passwort zu johnjohn durch einen Rest Anruf ändern, dann versuchen Sie, wenn das Passwort überprüfen tatsächlich

Meine Unittest Datei

import json 
import urllib 
import urllib2 

import requests 
from django.contrib.auth.models import User 

from django.test import TestCase 
from adaptors.redis_class import DjangoRedis 


class PasswordChange(TestCase): 
    def setUp(self): 
     User.objects.create_user(username='john', email='[email protected]', password='john') 
     # class for redis access 
     r = DjangoRedis() 
     r.set("email:[email protected]", '0' * 40, ex=3600) 
     r.set('0' * 40, "email:[email protected]", ex=3600) 
    def test_change_password(self): 
     # Fake url I set through redis 
     url = 'http://127.0.0.1:8000/reset/' + '0' * 40 + '/' 
     r = requests.get(url) 
     csrf_token = r.content.split('csrf_token')[1].split('"')[2] 
     payload = {'csrfmiddlewaretoken': csrf_token, 'payload': json.dumps({'password': 'johnjohn'})} 
     headers = {'Cookie': 'csrftoken=' + csrf_token} 
     data = urllib.urlencode(payload) 
     req = urllib2.Request(url, data, headers) 
     response = urllib2.urlopen(req) 
     json_res = json.loads(response.read()) 

     # This doesn't fail 
     self.assertEqual(json_res['password_changed'], True) 
     u = User.objects.get(username='john') 

     # This fails 
     self.assertEqual(u.check_password('johnjohn'),True) 

Meine Ansicht geändert wird

import hashlib 
import random 

from django.contrib.auth.models import User 
from django.core.exceptions import ObjectDoesNotExist 
from django.http import Http404 
from django.http import JsonResponse 
from django.shortcuts import render 
from django.views.generic import View 

from adaptors.redis_class import DjangoRedis 
from constants import PASSWORD_RESET 
from tasks import send_email 
from util.rest import get_payload 
class ResetPage(View): 
    def post(self, requests, reset_token): 
     r = DjangoRedis() 
     token = r.get(reset_token) 
     if token is None: 
      return JsonResponse({"token": False}) 
     payload = get_payload(requests.POST) 
     try: 
      email = token.split(':')[1].lower() 
      u = User.objects.get(email=email) 
      u.set_password(payload['password']) 
      u.save() 
      r.delete(reset_token) 
      r.delete('email:' + email) 
      return JsonResponse({'password_changed': True}) 
     except ValueError: 
      return JsonResponse({"password_changed": False, 'error': "can't get your email from the database (E01)"}) 
     except ObjectDoesNotExist: 
      return JsonResponse({"password_changed": False, 'error': "User doesn't exist (E02)"}) 

    def get(self, requests, reset_token): 
     r = DjangoRedis() 
     if not r.get(reset_token): 
      raise Http404 
     return render(requests, "login/reset.html", {'token': reset_token}) 

Die Unitest-Datei heißt rest_pass_login_tests.py in einem Verzeichnis unittests.

Ich starte es mit dem folgenden Befehl.

./manage.py test unittests/ --pattern="rest_pass_login_tests.py"

Wenn ich normal über den Browser zu testen, funktioniert die Kennwortänderung in Ordnung. Wenn ich jedoch versuche, durch einen Unittest zu überprüfen, ob das Passwort geändert wurde oder nicht, bekomme ich ein ungültiges Passwort.

Was mache ich falsch?

+0

Warum verwenden Sie nicht Django Test Client anstelle von Urllib? – AKS

+0

Ich verwende Selen, und ich habe den Code geändert, um urllib zu verwenden.Allerdings haben Sie Recht über django Test-Client – Ahmed

Antwort

0

Sie machen keine http post, wie Ihre Ansicht erwartet.

Hier ist, wie einen Beitrag machen urllib2 mit: Making a POST call instead of GET using urllib2

Aber, da Sie bereits requests Modul verwenden, warum nicht einfach tun:

url = 'http://127.0.0.1:8000/reset/' + '0' * 40 + '/' 
payload = {'csrfmiddlewaretoken': csrf_token, 'payload': json.dumps({'password': 'johnjohn'})} 
headers = {'Cookie': 'csrftoken=' + csrf_token} 
r = requests.post(url, data=payload, headers=headers) 
json_res = json.loads(r.content) 

Und vielleicht versuchen Debugging/Druck den Wert von json_res zu Überprüfen Sie, ob noch etwas unerwartetes vorhanden ist.

Beachten Sie auch, dies ist ein Integrationstest, wie Sie über HTTP testen, so dass Ihre urls.py, views.py und sogar settings.py als Teil davon getestet werden.

+0

'' '[04/May/2016 03:18:48]" GET/Reset/0000000000000000000000000000000000000000/HTTP/1.1 "200 3058 [04/Mai/2016 03:18: 48] "POST/Reset/000000000000000000000000000000000000000000/HTTP/1.1" 200 26 '' 'Nein, ich mache einen korrekten Beitrag. Allerdings werde ich Ihren Code testen – Ahmed

+0

'' '{u'password_changed ': True}' ''. Ich habe ein CBV, und zwei Methoden, eine für bekommen, und eine für die Post. Ich bin 100% sicher, dass es den Post eins – Ahmed

+0

Ich habe versucht, E2E-Test über Selen zu tun, und ich habe das gleiche Problem. Ich entfernte den UI-Teil und begann, nur Integrationstest zu machen – Ahmed

1

Ich verwendete Dev-Server, um Unittests auszuführen. Als ich mein Passwort änderte, posten wir tatsächlich auf dem Dev-Server anstatt auf dem Testserver.

Hier ist meine neue Unittest

import json 

from django.contrib.auth.models import User 
from django.test import Client 
from django.test import TestCase 

from adaptors.redis_class import DjangoRedis 


class PasswordChange(TestCase): 
    def setUp(self): 
     User.objects.create_user(username='john', email='[email protected]', password='john') 
     r = DjangoRedis() 
     r.set("email:[email protected]", '0' * 40, ex=3600) 
     r.set('0' * 40, "email:[email protected]", ex=3600) 

    def test_change_password(self): 
     c = Client() 
     payload = {'payload': json.dumps({'password': 'johnjohn'})} 

     url = '/reset/' + '0' * 40 + '/' 
     res = c.post(url, payload) 
     res = res.json() 
     self.assertEqual(res['password_changed'], True) 
     u = User.objects.get(username='john') 
     self.assertEqual(u.check_password('johnjohn'), True) 

Wenn Sie selenium IDE verwenden werden, stellen Sie sicher, dass Sie inhärenten aus StaticLiveServerTestCase statt Unittest. Folgen Sie this example. Auch vergessen Sie nicht diese Variable self.base_url-self.live_server_url

Diese in meinem setUp Methode fips,

self.base_url = self.live_server_url

Dank koterpillar mich für die Unterstützung auf dem IRC-Kanal zu ändern, und aks für unter mir zu kommentieren .