Я пытаюсь настроить тесты для моего DRF API. У меня есть 2 модели:
class Project(models.Model):
name = models.CharField(max_length=300, unique=True)
description = models.CharField(
max_length=2000,
blank=True,
null=True,
default=None
)
created_at = models.DateTimeField(auto_now_add=True)
class TemporaryUser(models.Model):
username = models.CharField(max_length=400)
hash_id = models.URLField(default=_generate_unique_hash, unique=True)
project = models.ForeignKey(
Project,
on_delete=models.CASCADE,
related_name='users'
)
Я решил разделить методы setUp для каждого тестового файла, поэтому мои 2 тестовых файла выглядят так:
test_projects.py
class ProjectViewsTest(APITestCase):
client = APIClient()
@classmethod
def setUpClass(cls):
project = Project.objects.create(name="Test Project")
cls.project_creation_date = datetime.now().strftime(
'%Y-%m-%d %H:%M:%S'
)
Project.objects.create(
name="Test Project #2", description='Testing Project Number 2'
)
session = QuestionSession.objects.create(project=project)
cls.session_creation_date = datetime.now().strftime(
'%Y-%m-%d %H:%M:%S'
)
Question.objects.create(
description='Test Question #1',
question_type='TEXT',
answers_to_close=50,
question_session=session
)
Question.objects.create(
description='Test Question #2',
question_type='TEXT',
answers_to_close=50,
question_session=session
)
Question.objects.create(
description='Test Question #3',
question_type='TEXT',
answers_to_close=50,
question_session=session
)
@classmethod
def tearDownClass(cls):
Project.objects.all().delete()
def test_projects_fetched_with_sessions_number(self):
"""Test multiple projects are fetched with sessions counter"""
self.maxDiff = None
response = self.client.get(
'http://testserver/api/projects/', format='json'
)
self.assertEqual(response.status_code, 200)
self.assertJSONEqual(
response.content,
{
"projects": [
{
"id": 1,
"name": "Test Project",
"description": None,
"sessions_number": 1,
"created_at": self.project_creation_date
},
{
"id": 2,
"name": "Test Project #2",
"description": "Testing Project Number 2",
"sessions_number": 0,
"created_at": self.project_creation_date
}
]
}
)
def test_project_fetched_with_minified_sessions(self):
"""Test a project is fetched with minified sessions"""
response = self.client.get(
'http://testserver/api/projects/1/',
format='json'
)
self.assertEqual(response.status_code, 200)
self.assertJSONEqual(
response.content,
{
"id": 1,
"name": "Test Project",
"created_at": self.project_creation_date,
"sessions": [
{
"id": 1,
"name": None,
"active": True,
"created_at": self.session_creation_date,
"priority": 0,
"questions_number": 3
}
]
}
)
def test_project_creation(self):
"""Test project creation with/without passing description"""
# POST with description
response_1 = self.client.post(
'http://testserver/api/projects/create/',
format='json',
data={"name": "Test Project #3", "description": "Another Project"}
)
# POST without description
response_2 = self.client.post(
'http://testserver/api/projects/create/',
format='json',
data={"name": "Test Project #4"}
)
self.assertEqual(response_1.status_code, 200)
self.assertEqual(response_2.status_code, 200)
self.assertJSONEqual(
response_1.content,
{
'status': 'SUCCESS', 'id': 3,
'message': 'Test Project #3 has been created successfully!'
}
)
self.assertJSONEqual(
response_2.content,
{
'status': 'SUCCESS', 'id': 4,
'message': 'Test Project #4 has been created successfully!'
}
)
project_1 = Project.objects.get(id=3)
project_2 = Project.objects.get(id=4)
self.assertEqual(project_1.description, "Another Project")
self.assertEqual(project_2.description, "")
def test_project_deletion(self):
"""Test API call removes Project from database"""
self.assertTrue(Project.objects.filter(id=1).exists())
response = self.client.delete(
'http://testserver/api/projects/1/delete/',
format='json'
)
self.assertEqual(response.status_code, 200)
self.assertJSONEqual(
response.content,
{
'status': 'SUCCESS',
'message': 'The project #1 has been deleted'
}
)
self.assertFalse(Project.objects.filter(id=1).exists())
и test_users.py
class TemporaryUserViewsTest(APITestCase):
client = APIClient()
@classmethod
def setUpClass(cls):
project = Project.objects.create(name="Test Project")
Project.objects.create(
name="Test Project #2", description='Testing Project Number 2'
)
TemporaryUser.objects.create(
username="TestUser", project=project
)
@classmethod
def tearDownClass(cls):
Project.objects.all().delete()
def test_created_user_exists(self):
"""Tests if a user is unique per project"""
response_1 = self.client.get(
'http://testserver/api/projects/1/temp_user/TestUser/exists/',
format='json'
)
response_2 = self.client.get(
'http://testserver/api/projects/2/temp_user/TestUser/exists/',
format='json'
)
self.assertEqual(response_1.status_code, 200)
self.assertEqual(response_2.status_code, 200)
self.assertJSONEqual(response_1.content, {"exists": True})
self.assertJSONEqual(response_2.content, {"exists": False})
def test_user_created_for_specific_project(self):
"""Test if a user is created and exists for a specific project"""
response_1 = self.client.post(
'http://testserver/api/temp_user/create/',
format='json',
data={"username": "TestUser2", "project_id": 2}
)
user = TemporaryUser.objects.get(username='TestUser2')
self.assertEqual(response_1.status_code, 200)
self.assertEqual(json.loads(response_1.content)['created'], True)
self.assertEqual(len(user.hash_id), 15)
self.assertEqual(user.username, "TestUser2")
response_2 = self.client.get(
'http://testserver/api/projects/2/temp_user/TestUser2/exists/',
format='json'
)
self.assertEqual(response_2.status_code, 200)
self.assertJSONEqual(response_2.content, {"exists": True})
def test_user_not_created_twice(self):
"""Test a user can't be created twice"""
response_1 = self.client.post(
'http://testserver/api/temp_user/create/',
format='json',
data={"username": "TestUser3", "project_id": 1}
)
response_2 = self.client.post(
'http://testserver/api/temp_user/create/',
format='json',
data={"username": "TestUser3", "project_id": 1}
)
self.assertEqual(response_1.status_code, 200)
self.assertEqual(response_2.status_code, 200)
self.assertEqual(json.loads(response_1.content)['created'], True)
self.assertEqual(json.loads(response_2.content)['created'], False)
Когда я запускаю эти 2 теста по отдельности, например ./manage.py test core.tests.test_users
и ./manage.py test core.tests.test_projects
, они работают как положено, без каких-либо ошибок.
Но когда я запускаю ./manage.py test core.tests
, происходит сбой в test_user_not_created_twice () и test_user_created_for_specific_project () с:
Запрос на сопоставление проекта не существует
Что не так? Я даже добавил Project.objects.all (). Delete () в методы tearDownClass, это не помогло.
А также, является ли хорошей практикой указывать методы setUpClass, подобные этой?