Locust: Understanding cookie creation while using locust login - python-2.7

I am trying to use locust for login to my web application. I am at very beginning of using locust.
I am using the following code for login to application.
post_data = {'username': username, 'password': password,'Submit':'Login' }
with self.client.post('/mylogin-url/', post_data,
catch_response=True) as response:
print response.code
print response.content
This part always returns status code 200 but the login is not succesful, as the response content of source is not the same as the actual source after login
My web application creates cookies and redirect to an URL based on cookie after login. I am trying to understand whether the login operation does this cookie creation automatically from locust or do I need to add that part of cookie creation logic n the script itself.
Any help regarding this is greatly appreciated.
Thanks

You may need to look at this.
In your with block, you can parse the response and check if you get the correct response.
Suppose you should get cookie field in your response cookies if you login success, then you can do like this:
post_data = {'username': username, 'password': password,'Submit':'Login' }
with self.client.post('/mylogin-url/', post_data, \
catch_response=True) as response:
if 'cookie' not in respone.cookies:
response.failure('login failed')

It seems that the response in the html content tells that user hasn't logged in. In that case you can check if response text contains failure message
post_data = {'username': username, 'password': password,'Submit':'Login' }
with self.client.post('/mylogin-url/', post_data,
catch_response=True) as response:
if response.text.contains("Login failed"):
response.failure('login failed')

Related

Django sessionid not created for Locust client

I'm running Django 2.2.24 and Locust 2.1.0 for load testing. When I run some Locust test logging in as a the Django admin user, there are no issues - all my GETs work as expected.
Now I am actually logging in as a specific user. From a web interface, Django passes a CSRFtoken and a sessionid token with no problem. From the Locust client however, the sessionid does not show up at all. Not only that, but when I look in the django_session table (where the web tokens do exist), there are no tokens for the Locust client.
I think this is more related to Django session management than to locust - hence the post in this forum.
My locust file looks like this:
def on_start(self):
'''
The start script for each user - this order is important
'''
# Below 3 lines work fine - we get the csrftoken and put it in the header successfully
response = self.client.get("/accounts/login")
self.csrftoken = response.cookies['csrftoken']
self.headers = {'X-CSRFToken': self.csrftoken}
# Now login with username and password as POST
r1 = self.login()
return r1
def login(self):
# admin login and retrieving it's access token
udata = {'username': self.username, 'password': self.password}
cookies=self.client.cookies.get_dict())
#csrftoken cookie does exist, sessionid does not yet.
log.info("Current cookies in Login:" + str(self.client.cookies))
# This next line should come back with a sessionid
# from Django - but it does not.
response = self.client.post("/accounts/login/",
data=json.dumps(udata),
headers=self.headers)
log.info("Response from client.post="+str(response)) #OK
log.info("Response status code:" + str(response.status_code))
log.info("Response text=" + response.text)
# Next line does not contain sessionid or Set-Cookie
log.info("Headers from post/accts/login = " + str(response.headers))
Thanks for any assistance.
Change
response = self.client.post("/accounts/login/",
data=json.dumps(udata),
headers=self.headers)
to
response = self.client.post("/accounts/login/",
json=udata,
headers=self.headers)
… to get the appropriate json headers. Or use:
response = self.client.post("/accounts/login/",
data=udata,
headers=self.headers)
in order to send it as form-encoded data instead of json.

Jsonresponse in Django working in browser but not in PostMan or Angular

I am trying to send a JSON response from Django back-end to my angular front-end.
When I make the request I receive nothing in Postman or Angular but,opening the link in browser seems to be returning the correct result
My View is :
#api_view(['GET'])
def my_view(request):
print(request.user.username)
return JsonResponse({'username': request.user.username})
When I open http://127.0.0.1:8000/accounts/get_username/ in browser I receive
{"username": "aditya8010"} on the web page.
But when i do a get request using POSTMAN I recieve
{
"username": ""
}
Same with Angular
this.http.get("http://127.0.0.1:8000/accounts/get_username/").subscribe((res) => {
this.username = JSON.stringify(res["username"])
console.log(this.username," ", res)
})
this code also prints an empty username string.
Another thing I have noticed is that my print statement in the view does print anything random I put in there when called from POSTMAN or Browser but when I use request.user.username it doesnt print anything when called by POSTMAN.
And each time the response code is 200
What am I doing wrong.
When you're sending the request you are not providing authentication credentials (i.e. something that identifies the user that is sending the request). How do you obtain this credentials?
You need to establish an authentication method. There are several but I recommend using Token authentication with knox package. Basically, you have an endpoint that logins the user with his username and password (normal json post request) and that endpoint returns a token. This token is what identifies the user. You send this token in the header of each request you need to be authenticated. That means you probably should include an IsAuthenticated permission for the view. In postman:
API view:
from rest_framework.permissions import IsAuthenticated
#api_view(['GET'])
#authentication_classes([IsAuthenticated])
def my_view(request):
print(request.user.username)
return JsonResponse({'username': request.user.username})
When it is in a browser, your login information is remembered in the session. When using postman or Angular, you need to provide the user's information in the request header manually.

Django testing, after login still get response 302, expecting 200

I'm testing django app login part.
my work flow is client.get('/run/experiment/1') -> response 302, redirect to login page -> client.post('loginpage', {'username': 'tester', 'password': 'tester'}) -> client.get('/run/experiment/1') -> response 200.
I have tested this flow in shell (type and execute the command line by line), and it worked as expected.
But when I write the test file, even after post the login, I still got the status 302 when trying to client.get.
Here is my code:
from django.test import TestCase, Client
class TestRunRequireLogin(TestCase):
def setUp(self):
self.client = Client()
def test_rerun_not_login(self):
response = self.client.get('/experiment/1')
self.assertEqual(response.status_code, 302)
def test_rerun_login(self):
self.client.post('/accounts/login/?next=/run/experiment/1', {'username': 'tester', 'password': 'tester'})
response = self.client.get('/experiment/1')
self.assertEqual(response.status_code, 200)
So my question is when in test_rerun_login, why I still got 302 after login
Do you have users? Do you have a user with username tester and password tester? If so you need to create them in your testcase.
Might be handy to post your view up there.Can you print the form.errors? You might find the answer there.
Tests are run against an empty database. You need to create a user in the setUp method.

Test REST service based on request.user

I build SPA on Django and I want to GET and POST JSON data based on request.user.
Something like this:
def get(self, *args, **kwargs):
return {
"data": [
i.get_json() for i in Customer.objects.filter(pk=self.request.user.pk)]
}
But I confuse, how it possible to put my user in request by REST service, like "Postman" or "Curl".
Postman has "Authorization" field, so I put login and password into it and my headers update with:
Authorization Basic YWdlbmN5X3NwYUBtYWlsLnJ1OjExMTEx
And I test it with curl:
curl -u myuser:11111 http://127.0.0.1:8000/api/myurl/
But user still - AnonymousUser
It could work with angular later, but I don't understand how I can test it now.
I found solution. I need to login with my user first and take sessionid from Cookie, then put sessionid in request.
Postman has nice extension named "Postman Interceptor", it put all session from browser into request authomaticly.

django tests response.request.user.is_authenticated() returning True after logout

I am trying to write some tests for the authentication part of my application and I encountered a problem with checking if the user is logged in or not. Here's the code:
client = Client()
# user signup form
response = client.post(signup_url, data={
'email': "lorem#ipsum.pl",
'password1': 'hunter2',
'password2': 'hunter2',
}, follow=True)
# checking if the user is logged in
with self.assertRaises(KeyError):
client.session['_auth_user_id']
self.assertEquals(len(mail.outbox), 1)
url = find_verification_url(mail.outbox[0].body)
response = client.get(url, follow=True)
self.assertEqual(200, response.status_code)
user = User.objects.get(email="lorem#ipsum.pl")
self.assertEqual(client.session['_auth_user_id'], user.pk)
# how to logout a user?
force_logout()
self.assertFalse(response.request.user.is_authenticated())
The user fills the form and clicks submit, then receives an email with a verification url. After he clicks the verification url in the email he's supposed to get directed to the site and authenticated. My questions is, what is a good way to find out if the user is authenticated or not? What is a preferred way to log out a user in this situation? I want to check that if the user is logged out and clicks the link the verification link second time it doesn't work. I tried some things like:
client.logout()
But unfortunately it seems to work once every two times even when I remove this line.
Thanks for any help!
Ok so the problem was that the authentication system was using a timestamp function to know if a url was expired or not. When run in a test the verification url was not expired when it should be. The login request after the logout was too fast and the system was thinking that the verification url was still valid and the user got authenticated. And that's why user.is_authenticated() was returning True all the time.