Fixtures are not meant to be called directly - django

I'm using Django 3.0.5, pytest 5.4.1 and pytest-django 3.9.0. I want to create a fixture that returns a User object to use in my tests.
Here is my conftest.py
import pytest
from django.contrib.auth import get_user_model
#pytest.fixture
def create_user(db):
return get_user_model().objects.create_user('user#gmail.com', 'password')
Here is my api_students_tests.py
import pytest
from rest_framework.test import APITestCase, APIClient
class StudentViewTests(APITestCase):
user = None
#pytest.fixture(scope="session")
def setUp(self, create_user):
self.user = create_user
def test_create_student(self):
assert self.user.email == 'user#gmail.com'
# other stuff ...
I keep getting the following error
Fixture "setUp" called directly. Fixtures are not meant to be called directly,
but are created automatically when test functions request them as parameters.
I read and read again this previous question but I cannot find out a solution. Furthermore, in that question the fixture wasn't returning nothing, while in my case it should return an object (don't know if it can make any difference)

Just skip the setUp:
#pytest.fixture(scope='session')
def create_user(db):
return get_user_model().objects.create_user('user#gmail.com', 'password')
class StudentViewTests(APITestCase):
def test_create_student(self, create_user):
assert user.email == 'user#gmail.com'
# other stuff ...

Related

Django test setup not being used

I am using Django cookiecutter 1.11 for a project.
Trying to write some basic tests for a model. But the setup method is not being used in the test cases.
from django.test import TestCase
from myapp.users.models import User
from ..models import Book
class ModelTests(TestCase):
def setup(self):
self.username = 'john'
self.password = '123'
self.user = User.objects.create(name=self.username,
password=self.password
)
def test_create_book(self):
Book.objects.create(artist=self.user,
title=“An Art Book“,
category=“Art”,
)
self.assertEquals(Book.objects.all().count(), 1)
I get this error message after running manage.py test
Book.objects.create(artist=self.user,
AttributeError: 'ModelTests' object has no attribute 'user'
But it works when I put the lines from setup into the test case.
Did I miss something?
The method should be called setUp, not setup.

Django pytest-selenium functional tests

I've created the tests folder, written my first test that should open a browser, point to a page and login, then go to home page.
Test run and fail, as expected, but I can't find out why.
browser should be available, pytest-selenium is installed by pip.
import pytest
from django.contrib.auth.models import Group, Permission, User
from django.test import TestCase, RequestFactory
class CreaPageTest(TestCase):
def setUp(self):
self.factory = RequestFactory()
def test_homepage(self):
request = self.client.get('/new')
request.user = self.user
self.assertEqual(request.status_code, 200)
def test_login(self):
request = self.client.get('/per/login')
username_field = self.browser.find_element_by_name('username')
username_field.send_keys('peppa')
password_field = self.browser.find_element_by_name('password')
password_field.send_keys('pig')
password_field.send_keys(Keys.RETURN)
test_homepage()
> username_field = self.browser.find_element_by_name('username')
E AttributeError: 'CreaPageTest' object has no attribute 'browser'
tests/test_ore_app_views.py:27: AttributeError
what am I missing?
Any advice to examples of this kind of test is really appreciated.
You should configure self.browser inside setUp function. You are also missing an import for Keys. Code should be like this.
import pytest
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from django.contrib.auth.models import Group, Permission, User
from django.test import TestCase, RequestFactory
class CreaPageTest(TestCase):
def setUp(self):
self.factory = RequestFactory()
self.browser = webdriver.Firefox()
Also please refer to the docs, here http://selenium-python.readthedocs.org/getting-started.html

Django AttributeError: object has no attribute 'assertContains'

I'm trying Django test fixtures from the official documentation, but my test class can't find assertContains.
from django.utils import unittest
from django.test import Client
class SimpleTest(unittest.TestCase):
def setUp(self):
self.client = Client()
def test_details(self):
response = self.client.post('/register',
{'username': '123',
'password': '123',
follow=True)
self.assertEqual(response.status_code, 200)
self.assertContains(response, "Logout")
self.assertNotContains(response, "Login")
assertContains is a Django specific feature, not Python specific. Thus, make sure the test class is subclassed from TestCase in django.test, not TestCase in (python) unittest.
i.e.
from django.test import TestCase
class SimpleTest(TestCase):
self.assertContains(response, "Logout")
That's it (the first answer), In my case, i'm using django test_plus, and thats was the issue:
from django.test import TestCase
class BlogTestCase(TestCase):
def test_blog(self):
response = self.get('blog_detail', self.blog.slug)
Change the import to
from test_plus.test import TestCase

use factoryboy for django User with py.test

I am migrating the UnitTests of a Django app to py.test, but in the UnitTests they make use of factory-boy to create instances of django.contrib.auth.models.User. how can this be done with pytest-factory-boy?
Creating a user in py.test, without to need for a factory is quite simple.
py.test already has a helper containing a builtin Django admin_user and admin_client fixture as explained here.
Here some code, for usage in your conftest.py to create a normal user:
import pytest
from django.contrib.auth.models import User
#pytest.fixture
def user_client(client):
"""
User fixture for tests with unprivileged user
"""
user = User.objects.create_user(
username='user',
password='pass',
first_name='Normal',
last_name='User'
)
response = client.post(reverse('login'), data={'username': 'user', 'password': 'pass'})
assert response.status_code == 302
return user_client

Accessing the request.user object when testing Django

I'm trying to access the request.user object when testing my app using django's client class.
from django.test import TestCase
from django.test.client import Client
class SomeTestCase(TestCase):
def setUp(self):
self.client = Client()
self.client.login( username="foo", password="bar")
def test_one(self):
response = self.client.get("/my_profile/")
self.fail( response.request.user )
This will obviously fail, but it fails because response.request doesn't have a user attribute.
AttributeError: 'dict' object has no attribute 'user'
Is there any way to access the user object from the client instance? I want to do this in order to check if some test user's data is properly rendered. I can try to tackle this by setting up all the necessary info during setUp, but before I do that I wanted to check if I'm not just missing something.
This may seem a roundabout way of doing it but it can be useful.
Use RequestFactory, its pretty straightforward. It imitates the request object.
from django.test import TestCase, RequestFactory
from django.test.client import Client
from django.contrib.auth.models import User
class SomeTestCase(TestCase):
def setUp(self):
self.client = Client()
self.factory = RequestFactory()
self.user = User.objects.create_user(
username='foo', email='foo#bar',
password='bar')
def test_one(self):
self.client.login( username="foo", password="bar")
request = self.factory.get("/my_profile/")
request.user = self.user
#rest of your code
def tearDown(self):
self.user.delete()
I hope that was helpful.
Use response.context['user'].
User is automatically available in the template context if you use RequestContext. See auth data in templates doc.
Otherwise i believe you should just query it:
def test_one(self):
response = self.client.get("/my_profile/")
user = User.objects.get(username="foo")
self.fail( user.some_field == False )