创建中心任务的管理系统
This commit is contained in:
0
tasks/tests/__init__.py
Normal file
0
tasks/tests/__init__.py
Normal file
BIN
tasks/tests/__pycache__/__init__.cpython-311.pyc
Normal file
BIN
tasks/tests/__pycache__/__init__.cpython-311.pyc
Normal file
Binary file not shown.
BIN
tasks/tests/__pycache__/test_api.cpython-311-pytest-8.3.2.pyc
Normal file
BIN
tasks/tests/__pycache__/test_api.cpython-311-pytest-8.3.2.pyc
Normal file
Binary file not shown.
BIN
tasks/tests/__pycache__/test_api.cpython-311.pyc
Normal file
BIN
tasks/tests/__pycache__/test_api.cpython-311.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
tasks/tests/__pycache__/test_factories.cpython-311.pyc
Normal file
BIN
tasks/tests/__pycache__/test_factories.cpython-311.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
tasks/tests/__pycache__/test_integration.cpython-311.pyc
Normal file
BIN
tasks/tests/__pycache__/test_integration.cpython-311.pyc
Normal file
Binary file not shown.
BIN
tasks/tests/__pycache__/test_models.cpython-311-pytest-8.3.2.pyc
Normal file
BIN
tasks/tests/__pycache__/test_models.cpython-311-pytest-8.3.2.pyc
Normal file
Binary file not shown.
BIN
tasks/tests/__pycache__/test_models.cpython-311.pyc
Normal file
BIN
tasks/tests/__pycache__/test_models.cpython-311.pyc
Normal file
Binary file not shown.
BIN
tasks/tests/__pycache__/test_views.cpython-311-pytest-8.3.2.pyc
Normal file
BIN
tasks/tests/__pycache__/test_views.cpython-311-pytest-8.3.2.pyc
Normal file
Binary file not shown.
BIN
tasks/tests/__pycache__/test_views.cpython-311.pyc
Normal file
BIN
tasks/tests/__pycache__/test_views.cpython-311.pyc
Normal file
Binary file not shown.
128
tasks/tests/test_api.py
Normal file
128
tasks/tests/test_api.py
Normal file
@@ -0,0 +1,128 @@
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APIClient
|
||||
from tasks.models import Client, Task, TaskResult
|
||||
from tasks.tests.test_factories import ClientFactory, TaskFactory, TaskResultFactory
|
||||
|
||||
class TaskAPITest(TestCase):
|
||||
def setUp(self):
|
||||
self.client = APIClient()
|
||||
# Create a test client with token
|
||||
self.test_client = ClientFactory()
|
||||
self.token = self.test_client.token
|
||||
# Authenticate the client
|
||||
self.client.credentials(HTTP_AUTHORIZATION=f'Token {self.token}')
|
||||
|
||||
def test_task_list(self):
|
||||
"""Test that authenticated users can list tasks"""
|
||||
# Create some test tasks
|
||||
TaskFactory.create_batch(3)
|
||||
|
||||
url = reverse('task-list')
|
||||
response = self.client.get(url)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(len(response.data), 3)
|
||||
|
||||
def test_task_create(self):
|
||||
"""Test that authenticated users can create tasks"""
|
||||
url = reverse('task-list')
|
||||
data = {
|
||||
'name': 'test_task',
|
||||
'client_name': 'test_client',
|
||||
'script': 'echo "Hello World"',
|
||||
'timeout_seconds': 3600
|
||||
}
|
||||
|
||||
response = self.client.post(url, data, format='json')
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
self.assertEqual(Task.objects.count(), 1)
|
||||
self.assertEqual(Task.objects.get().name, 'test_task')
|
||||
|
||||
def test_task_claim(self):
|
||||
"""Test that clients can claim available tasks"""
|
||||
# Create a pending task
|
||||
TaskFactory(client_name='test_client')
|
||||
|
||||
url = reverse('task-claim')
|
||||
data = {
|
||||
'client_name': 'test_client'
|
||||
}
|
||||
|
||||
response = self.client.post(url, data, format='json')
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data['status'], 'assigned')
|
||||
self.assertEqual(response.data['assigned_to'], 'test_client')
|
||||
|
||||
def test_unauthenticated_access(self):
|
||||
"""Test that unauthenticated users cannot access API endpoints"""
|
||||
# Create a new client without authentication
|
||||
unauth_client = APIClient()
|
||||
|
||||
url = reverse('task-list')
|
||||
response = unauth_client.get(url)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
||||
|
||||
class ClientAPITest(TestCase):
|
||||
def setUp(self):
|
||||
self.client = APIClient()
|
||||
# Create a test client with token
|
||||
self.test_client = ClientFactory()
|
||||
self.token = self.test_client.token
|
||||
# Authenticate the client
|
||||
self.client.credentials(HTTP_AUTHORIZATION=f'Token {self.token}')
|
||||
|
||||
def test_client_list(self):
|
||||
"""Test that authenticated users can list clients"""
|
||||
# Create some test clients
|
||||
ClientFactory.create_batch(3)
|
||||
|
||||
url = reverse('client-list')
|
||||
response = self.client.get(url)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(len(response.data), 4) # Including the test client
|
||||
|
||||
def test_client_create(self):
|
||||
"""Test that authenticated users can create clients"""
|
||||
url = reverse('client-list')
|
||||
data = {
|
||||
'name': 'new_client'
|
||||
}
|
||||
|
||||
response = self.client.post(url, data, format='json')
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
self.assertEqual(Client.objects.count(), 2) # Including the test client
|
||||
self.assertEqual(Client.objects.get(id=response.data['id']).name, 'new_client')
|
||||
|
||||
class TaskResultAPITest(TestCase):
|
||||
def setUp(self):
|
||||
self.client = APIClient()
|
||||
# Create a test client with token
|
||||
self.test_client = ClientFactory()
|
||||
self.token = self.test_client.token
|
||||
# Authenticate the client
|
||||
self.client.credentials(HTTP_AUTHORIZATION=f'Token {self.token}')
|
||||
# Create a test task
|
||||
self.task = TaskFactory()
|
||||
|
||||
def test_task_result_create(self):
|
||||
"""Test that authenticated users can create task results"""
|
||||
url = reverse('taskresult-list')
|
||||
data = {
|
||||
'task': self.task.id,
|
||||
'client': self.test_client.id,
|
||||
'status': 'success',
|
||||
'message': 'Task completed successfully'
|
||||
}
|
||||
|
||||
response = self.client.post(url, data, format='json')
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
self.assertEqual(TaskResult.objects.count(), 1)
|
||||
self.assertEqual(TaskResult.objects.get().status, 'success')
|
||||
38
tasks/tests/test_factories.py
Normal file
38
tasks/tests/test_factories.py
Normal file
@@ -0,0 +1,38 @@
|
||||
import factory
|
||||
from django.utils import timezone
|
||||
from tasks.models import Client, Task, TaskResult
|
||||
|
||||
class ClientFactory(factory.django.DjangoModelFactory):
|
||||
class Meta:
|
||||
model = Client
|
||||
|
||||
name = factory.Sequence(lambda n: f"client_{n}")
|
||||
token = factory.Faker('uuid4')
|
||||
last_seen = timezone.now()
|
||||
created_at = timezone.now()
|
||||
|
||||
class TaskFactory(factory.django.DjangoModelFactory):
|
||||
class Meta:
|
||||
model = Task
|
||||
|
||||
name = factory.Sequence(lambda n: f"task_{n}")
|
||||
client_name = factory.Sequence(lambda n: f"client_{n}")
|
||||
script = factory.Faker('text')
|
||||
status = 'pending'
|
||||
timeout_seconds = 3600 # 1 hour
|
||||
created_at = timezone.now()
|
||||
updated_at = timezone.now()
|
||||
assigned_to = None
|
||||
started_at = None
|
||||
completed_at = None
|
||||
|
||||
class TaskResultFactory(factory.django.DjangoModelFactory):
|
||||
class Meta:
|
||||
model = TaskResult
|
||||
|
||||
task = factory.SubFactory(TaskFactory)
|
||||
client = factory.SubFactory(ClientFactory)
|
||||
result_file = None
|
||||
status = 'success'
|
||||
message = factory.Faker('text')
|
||||
created_at = timezone.now()
|
||||
89
tasks/tests/test_integration.py
Normal file
89
tasks/tests/test_integration.py
Normal file
@@ -0,0 +1,89 @@
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APIClient
|
||||
from tasks.models import Client, Task, TaskResult
|
||||
from tasks.tests.test_factories import ClientFactory, TaskFactory
|
||||
|
||||
class TaskFlowIntegrationTest(TestCase):
|
||||
def setUp(self):
|
||||
self.client = APIClient()
|
||||
# Create a test client with token
|
||||
self.test_client = ClientFactory()
|
||||
self.token = self.test_client.token
|
||||
# Authenticate the client
|
||||
self.client.credentials(HTTP_AUTHORIZATION=f'Token {self.token}')
|
||||
|
||||
def test_full_task_flow(self):
|
||||
"""Test the full task flow: create → claim → start → complete"""
|
||||
# 1. Create a task
|
||||
create_url = reverse('task-list')
|
||||
create_data = {
|
||||
'name': 'integration_test_task',
|
||||
'client_name': self.test_client.name,
|
||||
'script': 'echo "Integration Test"',
|
||||
'timeout_seconds': 3600
|
||||
}
|
||||
create_response = self.client.post(create_url, create_data, format='json')
|
||||
self.assertEqual(create_response.status_code, status.HTTP_201_CREATED)
|
||||
task_id = create_response.data['id']
|
||||
|
||||
# 2. Claim the task
|
||||
claim_url = reverse('task-claim')
|
||||
claim_data = {
|
||||
'client_name': self.test_client.name
|
||||
}
|
||||
claim_response = self.client.post(claim_url, claim_data, format='json')
|
||||
self.assertEqual(claim_response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(claim_response.data['status'], 'assigned')
|
||||
self.assertEqual(claim_response.data['assigned_to'], self.test_client.name)
|
||||
|
||||
# 3. Start the task
|
||||
start_url = reverse('task-start', args=[task_id])
|
||||
start_response = self.client.post(start_url, format='json')
|
||||
self.assertEqual(start_response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(start_response.data['status'], 'running')
|
||||
self.assertIsNotNone(start_response.data['started_at'])
|
||||
|
||||
# 4. Complete the task
|
||||
complete_url = reverse('task-complete', args=[task_id])
|
||||
complete_data = {
|
||||
'status': 'success',
|
||||
'message': 'Task completed successfully'
|
||||
}
|
||||
complete_response = self.client.post(complete_url, complete_data, format='json')
|
||||
self.assertEqual(complete_response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(complete_response.data['status'], 'success')
|
||||
self.assertIsNotNone(complete_response.data['completed_at'])
|
||||
|
||||
# 5. Verify the task status in database
|
||||
task = Task.objects.get(id=task_id)
|
||||
self.assertEqual(task.status, 'success')
|
||||
self.assertEqual(task.assigned_to, self.test_client.name)
|
||||
self.assertIsNotNone(task.started_at)
|
||||
self.assertIsNotNone(task.completed_at)
|
||||
|
||||
def test_task_result_upload(self):
|
||||
"""Test that a client can upload task results"""
|
||||
# Create a test task
|
||||
task = TaskFactory()
|
||||
|
||||
# Upload a task result
|
||||
upload_url = reverse('taskresult-list')
|
||||
upload_data = {
|
||||
'task': task.id,
|
||||
'client': self.test_client.id,
|
||||
'status': 'success',
|
||||
'message': 'Result uploaded successfully'
|
||||
}
|
||||
|
||||
upload_response = self.client.post(upload_url, upload_data, format='json')
|
||||
self.assertEqual(upload_response.status_code, status.HTTP_201_CREATED)
|
||||
|
||||
# Verify the result exists in database
|
||||
self.assertEqual(TaskResult.objects.count(), 1)
|
||||
result = TaskResult.objects.get()
|
||||
self.assertEqual(result.task, task)
|
||||
self.assertEqual(result.client, self.test_client)
|
||||
self.assertEqual(result.status, 'success')
|
||||
109
tasks/tests/test_models.py
Normal file
109
tasks/tests/test_models.py
Normal file
@@ -0,0 +1,109 @@
|
||||
from django.test import TestCase
|
||||
from django.utils import timezone
|
||||
from tasks.models import Client, Task, TaskResult
|
||||
|
||||
class ClientModelTest(TestCase):
|
||||
def test_client_creation(self):
|
||||
"""Test that a client can be created with all required fields"""
|
||||
client = Client.objects.create(
|
||||
name="test_client",
|
||||
token="test_token_12345"
|
||||
)
|
||||
|
||||
self.assertEqual(client.name, "test_client")
|
||||
self.assertEqual(client.token, "test_token_12345")
|
||||
self.assertIsNotNone(client.created_at)
|
||||
self.assertIsNotNone(client.last_seen)
|
||||
|
||||
def test_client_str(self):
|
||||
"""Test that the client string representation is correct"""
|
||||
client = Client.objects.create(
|
||||
name="test_client",
|
||||
token="test_token_12345"
|
||||
)
|
||||
|
||||
self.assertEqual(str(client), "test_client")
|
||||
|
||||
class TaskModelTest(TestCase):
|
||||
def test_task_creation(self):
|
||||
"""Test that a task can be created with all required fields"""
|
||||
task = Task.objects.create(
|
||||
name="test_task",
|
||||
client_name="test_client",
|
||||
script="echo 'Hello World'",
|
||||
timeout_seconds=3600
|
||||
)
|
||||
|
||||
self.assertEqual(task.name, "test_task")
|
||||
self.assertEqual(task.client_name, "test_client")
|
||||
self.assertEqual(task.script, "echo 'Hello World'")
|
||||
self.assertEqual(task.status, "pending")
|
||||
self.assertEqual(task.timeout_seconds, 3600)
|
||||
self.assertIsNotNone(task.created_at)
|
||||
self.assertIsNotNone(task.updated_at)
|
||||
|
||||
def test_task_str(self):
|
||||
"""Test that the task string representation is correct"""
|
||||
task = Task.objects.create(
|
||||
name="test_task"
|
||||
)
|
||||
|
||||
self.assertEqual(str(task), "test_task")
|
||||
|
||||
def test_task_status_choices(self):
|
||||
"""Test that task status choices are correctly implemented"""
|
||||
from tasks.models import STATUS_CHOICES
|
||||
status_choices = [choice[0] for choice in STATUS_CHOICES]
|
||||
|
||||
self.assertIn("pending", status_choices)
|
||||
self.assertIn("assigned", status_choices)
|
||||
self.assertIn("running", status_choices)
|
||||
self.assertIn("success", status_choices)
|
||||
self.assertIn("failed", status_choices)
|
||||
self.assertIn("retrying", status_choices)
|
||||
self.assertIn("timeout", status_choices)
|
||||
|
||||
class TaskResultModelTest(TestCase):
|
||||
def test_task_result_creation(self):
|
||||
"""Test that a task result can be created with all required fields"""
|
||||
client = Client.objects.create(
|
||||
name="test_client",
|
||||
token="test_token_12345"
|
||||
)
|
||||
|
||||
task = Task.objects.create(
|
||||
name="test_task"
|
||||
)
|
||||
|
||||
result = TaskResult.objects.create(
|
||||
task=task,
|
||||
client=client,
|
||||
status="success",
|
||||
message="Task completed successfully"
|
||||
)
|
||||
|
||||
self.assertEqual(result.task, task)
|
||||
self.assertEqual(result.client, client)
|
||||
self.assertEqual(result.status, "success")
|
||||
self.assertEqual(result.message, "Task completed successfully")
|
||||
self.assertIsNotNone(result.created_at)
|
||||
|
||||
def test_task_result_str(self):
|
||||
"""Test that the task result string representation is correct"""
|
||||
client = Client.objects.create(
|
||||
name="test_client",
|
||||
token="test_token_12345"
|
||||
)
|
||||
|
||||
task = Task.objects.create(
|
||||
name="test_task"
|
||||
)
|
||||
|
||||
result = TaskResult.objects.create(
|
||||
task=task,
|
||||
client=client,
|
||||
status="success"
|
||||
)
|
||||
|
||||
# Expected status display is in Chinese
|
||||
self.assertEqual(str(result), f"{task.name} - {client.name} - 成功")
|
||||
60
tasks/tests/test_views.py
Normal file
60
tasks/tests/test_views.py
Normal file
@@ -0,0 +1,60 @@
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
from tasks.models import Client, Task
|
||||
from tasks.tests.test_factories import ClientFactory, TaskFactory
|
||||
|
||||
class TaskViewTest(TestCase):
|
||||
def test_task_list_view(self):
|
||||
"""Test that the task list view renders correctly"""
|
||||
# Create some test tasks
|
||||
TaskFactory.create_batch(3)
|
||||
|
||||
url = reverse('task_list')
|
||||
response = self.client.get(url)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, 'tasks/task_list.html')
|
||||
self.assertContains(response, '任务列表')
|
||||
|
||||
def test_task_create_view(self):
|
||||
"""Test that the task create view renders correctly"""
|
||||
url = reverse('task_create')
|
||||
response = self.client.get(url)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, 'tasks/task_create.html')
|
||||
self.assertContains(response, '创建任务')
|
||||
|
||||
def test_task_detail_view(self):
|
||||
"""Test that the task detail view renders correctly"""
|
||||
# Create a test task
|
||||
task = TaskFactory()
|
||||
|
||||
url = reverse('task_detail', args=[task.id])
|
||||
response = self.client.get(url)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, 'tasks/task_detail.html')
|
||||
self.assertContains(response, task.name)
|
||||
|
||||
class ClientViewTest(TestCase):
|
||||
def test_client_list_view(self):
|
||||
"""Test that the client list view renders correctly"""
|
||||
# Create some test clients
|
||||
ClientFactory.create_batch(3)
|
||||
|
||||
url = reverse('client_list')
|
||||
response = self.client.get(url)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, 'tasks/client_list.html')
|
||||
self.assertContains(response, '客户端列表')
|
||||
|
||||
def test_client_create_view(self):
|
||||
"""Test that the client create view renders correctly"""
|
||||
url = reverse('client_create')
|
||||
response = self.client.get(url)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, 'tasks/client_create.html')
|
||||
self.assertContains(response, '创建客户端')
|
||||
Reference in New Issue
Block a user