软件工程结对作业测试代码
模块一:
`
import unittest
import uuid
from enum import Enum
from typing import List, Optional, Dict
Mock classes and exceptions for testing
class Role(Enum):
USER = "USER"
ADMIN = "ADMIN"
class InvalidEmailError(Exception):
pass
class UserAlreadyExistsError(Exception):
pass
class UserNotFoundError(Exception):
pass
class InvalidCredentialsError(Exception):
pass
class PermissionDeniedError(Exception):
pass
class User:
def init(self, user_id: str, username: str, email: str, password_hash: str, role: Role):
self.user_id = user_id
self.username = username
self.email = email
self.password_hash = password_hash
self.role = role
self.is_active = True
@staticmethod
def hash_password(password: str) -> str:
return f"hashed_{password}"
def verify_password(self, password: str) -> bool:
return self.password_hash == f"hashed_{password}"
UserManagement class (copied from provided code for completeness)
class UserManagement:
EMAIL_PATTERN = r'[1]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$'
def __init__(self):
self._users = {}
def _validate_email(self, email: str) -> None:
import re
if not re.match(self.EMAIL_PATTERN, email):
raise InvalidEmailError("Invalid email format")
def register_user(self, username: str, email: str, password: str, role: Role = Role.USER) -> str:
self._validate_email(email)
if email in self._users:
raise UserAlreadyExistsError("Email already registered")
user_id = str(uuid.uuid4())
password_hash = User.hash_password(password)
user = User(user_id=user_id, username=username, email=email, password_hash=password_hash, role=role)
self._users[email] = user
return user_id
def login_user(self, email: str, password: str) -> User:
if email not in self._users:
raise UserNotFoundError("User not found")
user = self._users[email]
if not user.is_active:
raise InvalidCredentialsError("Account is disabled")
if not user.verify_password(password):
raise InvalidCredentialsError("Incorrect password")
return user
def logout_user(self, email: str) -> None:
if email not in self._users:
raise UserNotFoundError("User not found")
def reset_password(self, email: str) -> str:
if email not in self._users:
raise UserNotFoundError("User not found")
reset_token = str(uuid.uuid4())
return reset_token
def update_password(self, email: str, new_password: str) -> None:
if email not in self._users:
raise UserNotFoundError("User not found")
user = self._users[email]
user.password_hash = User.hash_password(new_password)
def get_user_info(self, email: str, requesting_user: Optional[User]) -> User:
if email not in self._users:
raise UserNotFoundError("User not found")
user = self._users[email]
if requesting_user is not None and requesting_user.email != email and requesting_user.role != Role.ADMIN:
raise PermissionDeniedError("Permission denied")
return user
def get_user_by_id(self, user_id: str, requesting_user: Optional[User]) -> User:
for user in self._users.values():
if user.user_id == user_id:
if requesting_user is not None and requesting_user.user_id != user_id and requesting_user.role != Role.ADMIN:
raise PermissionDeniedError("Permission denied")
return user
raise UserNotFoundError(f"User {user_id} not found")
def list_users(self, requesting_user: User) -> List[User]:
if requesting_user.role != Role.ADMIN:
raise PermissionDeniedError("Permission denied")
return list(self._users.values())
def disable_user(self, target_email: str, requesting_user: User) -> None:
if requesting_user.role != Role.ADMIN:
raise PermissionDeniedError("Permission denied")
if target_email not in self._users:
raise UserNotFoundError("User not found")
self._users[target_email].is_active = False
def is_user_valid(self, user_id: str) -> bool:
for user in self._users.values():
if user.user_id == user_id:
return user.is_active
return False
def is_admin(self, user_id: str) -> bool:
for user in self._users.values():
if user.user_id == user_id and user.is_active:
return user.role == Role.ADMIN
return False
def are_users_valid(self, user_ids: List[str]) -> Dict[str, bool]:
return {user_id: self.is_user_valid(user_id) for user_id in user_ids}
Test cases for boundary condition coverage
class TestUserManagement(unittest.TestCase):
def setUp(self):
self.um = UserManagement()
self.user_id = self.um.register_user("testuser", "test@example.com", "password123", Role.USER)
self.admin_id = self.um.register_user("admin", "admin@example.com", "admin123", Role.ADMIN)
def test_validate_email_valid(self):
# Valid email formats
valid_emails = [
"a@b.co", # Minimum length domain
"user@domain.com", # Standard email
"user.name@sub.domain.co.uk", # Complex email with subdomains
"user+label@domain.com" # Email with + label
]
for email in valid_emails:
with self.subTest(email=email):
self.um._validate_email(email) # Should not raise exception
def test_validate_email_invalid(self):
# Invalid email formats
invalid_emails = [
"", # Empty string
"user@domain", # Missing top-level domain
"@domain.com", # Missing local part
"user@.com", # Missing domain
"user@domain.c", # Top-level domain too short
"user@domain..com", # Double dot
"user..name@domain.com", # Double dot in local part
"user@domain,com", # Invalid character
" user@domain.com" # Leading space
]
for email in invalid_emails:
with self.subTest(email=email):
with self.assertRaises(InvalidEmailError):
self.um._validate_email(email)
def test_register_user_valid(self):
# Valid registration
user_id = self.um.register_user("newuser", "newuser@example.com", "pass123")
self.assertIsNotNone(user_id)
self.assertTrue(isinstance(user_id, str))
self.assertIn("newuser@example.com", self.um._users)
def test_register_user_duplicate_email(self):
# Duplicate email
with self.assertRaises(UserAlreadyExistsError):
self.um.register_user("testuser2", "test@example.com", "password123")
def test_register_user_invalid_email(self):
# Invalid email format
with self.assertRaises(InvalidEmailError):
self.um.register_user("testuser2", "invalid.email", "password123")
def test_register_user_empty_inputs(self):
# Empty username, email, or password
with self.assertRaises(InvalidEmailError):
self.um.register_user("", "test2@example.com", "password123")
with self.assertRaises(InvalidEmailError):
self.um.register_user("testuser2", "", "password123")
with self.assertRaises(TypeError): # Assuming password validation in hash_password
self.um.register_user("testuser2", "test2@example.com", "")
def test_login_user_success(self):
# Successful login
user = self.um.login_user("test@example.com", "password123")
self.assertEqual(user.email, "test@example.com")
self.assertEqual(user.username, "testuser")
def test_login_user_not_found(self):
# Non-existent email
with self.assertRaises(UserNotFoundError):
self.um.login_user("nonexistent@example.com", "password123")
def test_login_user_incorrect_password(self):
# Incorrect password
with self.assertRaises(InvalidCredentialsError):
self.um.login_user("test@example.com", "wrongpassword")
def test_login_user_disabled_account(self):
# Disabled account
admin = self.um._users["admin@example.com"]
self.um.disable_user("test@example.com", admin)
with self.assertRaises(InvalidCredentialsError):
self.um.login_user("test@example.com", "password123")
def test_logout_user_valid(self):
# Valid logout
self.um.logout_user("test@example.com") # Should not raise exception
def test_logout_user_not_found(self):
# Non-existent email
with self.assertRaises(UserNotFoundError):
self.um.logout_user("nonexistent@example.com")
def test_reset_password_valid(self):
# Valid reset
token = self.um.reset_password("test@example.com")
self.assertIsNotNone(token)
self.assertTrue(isinstance(token, str))
def test_reset_password_not_found(self):
# Non-existent email
with self.assertRaises(UserNotFoundError):
self.um.reset_password("nonexistent@example.com")
def test_update_password_valid(self):
# Valid password update
self.um.update_password("test@example.com", "newpassword123")
user = self.um.login_user("test@example.com", "newpassword123")
self.assertEqual(user.email, "test@example.com")
def test_update_password_not_found(self):
# Non-existent email
with self.assertRaises(UserNotFoundError):
self.um.update_password("nonexistent@example.com", "newpassword123")
def test_get_user_info_self(self):
# User accessing own info
user = self.um._users["test@example.com"]
result = self.um.get_user_info("test@example.com", user)
self.assertEqual(result.email, "test@example.com")
def test_get_user_info_admin(self):
# Admin accessing user info
admin = self.um._users["admin@example.com"]
result = self.um.get_user_info("test@example.com", admin)
self.assertEqual(result.email, "test@example.com")
def test_get_user_info_unauthorized(self):
# Non-admin accessing another user's info
user = self.um._users["test@example.com"]
with self.assertRaises(PermissionDeniedError):
self.um.get_user_info("admin@example.com", user)
def test_get_user_info_not_found(self):
# Non-existent email
user = self.um._users["test@example.com"]
with self.assertRaises(UserNotFoundError):
self.um.get_user_info("nonexistent@example.com", user)
def test_get_user_by_id_self(self):
# User accessing own info by ID
user = self.um._users["test@example.com"]
result = self.um.get_user_by_id(user.user_id, user)
self.assertEqual(result.user_id, user.user_id)
def test_get_user_by_id_admin(self):
# Admin accessing user info by ID
admin = self.um._users["admin@example.com"]
user = self.um._users["test@example.com"]
result = self.um.get_user_by_id(user.user_id, admin)
self.assertEqual(result.user_id, user.user_id)
def test_get_user_by_id_unauthorized(self):
# Non-admin accessing another user's info by ID
user = self.um._users["test@example.com"]
admin = self.um._users["admin@example.com"]
with self.assertRaises(PermissionDeniedError):
self.um.get_user_by_id(admin.user_id, user)
def test_get_user_by_id_not_found(self):
# Non-existent user ID
user = self.um._users["test@example.com"]
with self.assertRaises(UserNotFoundError):
self.um.get_user_by_id("nonexistent-id", user)
def test_list_users_admin(self):
# Admin listing users
admin = self.um._users["admin@example.com"]
users = self.um.list_users(admin)
self.assertEqual(len(users), 2)
self.assertTrue(any(u.email == "test@example.com" for u in users))
self.assertTrue(any(u.email == "admin@example.com" for u in users))
def test_list_users_non_admin(self):
# Non-admin attempting to list users
user = self.um._users["test@example.com"]
with self.assertRaises(PermissionDeniedError):
self.um.list_users(user)
def test_disable_user_admin(self):
# Admin disabling user
admin = self.um._users["admin@example.com"]
self.um.disable_user("test@example.com", admin)
self.assertFalse(self.um._users["test@example.com"].is_active)
def test_disable_user_non_admin(self):
# Non-admin attempting to disable user
user = self.um._users["test@example.com"]
with self.assertRaises(PermissionDeniedError):
self.um.disable_user("admin@example.com", user)
def test_disable_user_not_found(self):
# Disabling non-existent user
admin = self.um._users["admin@example.com"]
with self.assertRaises(UserNotFoundError):
self.um.disable_user("nonexistent@example.com", admin)
def test_is_user_valid_valid(self):
# Valid user ID
user = self.um._users["test@example.com"]
self.assertTrue(self.um.is_user_valid(user.user_id))
def test_is_user_valid_invalid(self):
# Non-existent user ID
self.assertFalse(self.um.is_user_valid("nonexistent-id"))
def test_is_user_valid_disabled(self):
# Disabled user
admin = self.um._users["admin@example.com"]
self.um.disable_user("test@example.com", admin)
user = self.um._users["test@example.com"]
self.assertFalse(self.um.is_user_valid(user.user_id))
def test_is_admin_valid(self):
# Valid admin user
admin = self.um._users["admin@example.com"]
self.assertTrue(self.um.is_admin(admin.user_id))
def test_is_admin_non_admin(self):
# Non-admin user
user = self.um._users["test@example.com"]
self.assertFalse(self.um.is_admin(user.user_id))
def test_is_admin_invalid(self):
# Non-existent user ID
self.assertFalse(self.um.is_admin("nonexistent-id"))
def test_are_users_valid_mixed(self):
# Mixed valid, invalid, and disabled users
admin = self.um._users["admin@example.com"]
user = self.um._users["test@example.com"]
self.um.disable_user("test@example.com", admin)
user_ids = [user.user_id, admin.user_id, "nonexistent-id"]
result = self.um.are_users_valid(user_ids)
self.assertEqual(result, {
user.user_id: False,
admin.user_id: True,
"nonexistent-id": False
})
def test_are_users_valid_empty(self):
# Empty user ID list
result = self.um.are_users_valid([])
self.assertEqual(result, {})
if name == 'main':
unittest.main()
`
模块二:
`
import unittest
from unittest.mock import Mock
import uuid
import datetime
from typing import List, Optional
from enum import Enum
# Import classes from the provided TaskManager code
from task_manager import (
TaskManager, Task, TaskStatus, TaskPriority,
InvalidTaskError, InvalidDueDateError, PermissionDeniedError, InvalidUserError,
MemoryTaskStorage, IUserManager
)
# Mock Role enum for user manager
class Role(Enum):
USER = "USER"
ADMIN = "ADMIN"
# Mock User class for testing
class User:
def __init__(self, user_id: str, role: Role):
self.user_id = user_id
self.role = role
# Test cases for boundary condition coverage
class TestTaskManager(unittest.TestCase):
def setUp(self):
# Mock IUserManager
self.user_manager = Mock(spec=IUserManager)
self.user_manager.is_user_valid.side_effect = lambda user_id: user_id in ["user1", "admin1"]
self.user_manager.is_admin.side_effect = lambda user_id: user_id == "admin1"
# Initialize TaskManager with MemoryTaskStorage
self.task_manager = TaskManager(self.user_manager, MemoryTaskStorage())
# Create sample users
self.user1 = User("user1", Role.USER)
self.admin1 = User("admin1", Role.ADMIN)
# Create a future due date
self.future_date = datetime.datetime.now() + datetime.timedelta(days=1)
# Create a sample task for testing
self.task = self.task_manager.create_task(
title="Sample Task",
creator_id="user1",
due_date=self.future_date,
description="Test description",
priority=TaskPriority.MEDIUM.value
)
def test_create_task_valid(self):
# Valid task creation with minimal and maximal inputs
task = self.task_manager.create_task(
title="Test",
creator_id="user1",
due_date=self.future_date,
description="A" * 1000, # Long description
priority=TaskPriority.HIGH.value
)
self.assertIsNotNone(task.task_id)
self.assertEqual(task.title, "Test")
self.assertEqual(task.creator_id, "user1")
self.assertEqual(task.priority, TaskPriority.HIGH)
self.assertEqual(task.status, TaskStatus.TODO)
self.assertEqual(task.description, "A" * 1000)
self.assertEqual(task.due_date, self.future_date)
def test_create_task_empty_title(self):
# Empty title
with self.assertRaises(InvalidTaskError):
self.task_manager.create_task(
title="",
creator_id="user1",
due_date=self.future_date
)
def test_create_task_invalid_creator(self):
# Non-existent creator
with self.assertRaises(InvalidUserError):
self.task_manager.create_task(
title="Test",
creator_id="nonexistent",
due_date=self.future_date
)
def test_create_task_past_due_date(self):
# Past due date
past_date = datetime.datetime.now() - datetime.timedelta(days=1)
with self.assertRaises(InvalidDueDateError):
self.task_manager.create_task(
title="Test",
creator_id="user1",
due_date=past_date
)
def test_create_task_invalid_priority(self):
# Invalid priority
with self.assertRaises(InvalidTaskError):
self.task_manager.create_task(
title="Test",
creator_id="user1",
due_date=self.future_date,
priority="invalid"
)
def test_update_task_valid_creator(self):
# Creator updates all fields
new_due_date = self.future_date + datetime.timedelta(days=1)
self.task_manager.update_task(
task_id=self.task.task_id,
caller_id="user1",
title="Updated Title",
description="Updated Description",
priority=TaskPriority.LOW.value,
due_date=new_due_date,
status=TaskStatus.IN_PROGRESS.value
)
updated_task = self.task_manager.storage.get_task(self.task.task_id)
self.assertEqual(updated_task.title, "Updated Title")
self.assertEqual(updated_task.description, "Updated Description")
self.assertEqual(updated_task.priority, TaskPriority.LOW)
self.assertEqual(updated_task.due_date, new_due_date)
self.assertEqual(updated_task.status, TaskStatus.IN_PROGRESS)
self.assertIsNotNone(updated_task.updated_at)
def test_update_task_valid_admin(self):
# Admin updates all fields
new_due_date = self.future_date + datetime.timedelta(days=1)
self.task_manager.update_task(
task_id=self.task.task_id,
caller_id="admin1",
title="Updated Title",
description="Updated Description",
priority=TaskPriority.LOW.value,
due_date=new_due_date,
status=TaskStatus.IN_PROGRESS.value
)
updated_task = self.task_manager.storage.get_task(self.task.task_id)
self.assertEqual(updated_task.title, "Updated Title")
self.assertEqual(updated_task.description, "Updated Description")
self.assertEqual(updated_task.priority, TaskPriority.LOW)
self.assertEqual(updated_task.due_date, new_due_date)
self.assertEqual(updated_task.status, TaskStatus.IN_PROGRESS)
def test_update_task_unauthorized(self):
# Non-creator, non-admin tries to update
self.user_manager.is_user_valid.side_effect = lambda user_id: user_id in ["user1", "user2"]
self.user_manager.is_admin.side_effect = lambda user_id: False
with self.assertRaises(PermissionDeniedError):
self.task_manager.update_task(
task_id=self.task.task_id,
caller_id="user2",
title="Unauthorized Update"
)
def test_update_task_nonexistent_task(self):
# Non-existent task
with self.assertRaises(InvalidTaskError):
self.task_manager.update_task(
task_id="nonexistent",
caller_id="user1",
title="Test"
)
def test_update_task_empty_title(self):
# Empty title
with self.assertRaises(InvalidTaskError):
self.task_manager.update_task(
task_id=self.task.task_id,
caller_id="user1",
title=""
)
def test_update_task_invalid_priority(self):
# Invalid priority
with self.assertRaises(InvalidTaskError):
self.task_manager.update_task(
task_id=self.task.task_id,
caller_id="user1",
priority="invalid"
)
def test_update_task_invalid_status(self):
# Invalid status
with self.assertRaises(InvalidTaskError):
self.task_manager.update_task(
task_id=self.task.task_id,
caller_id="user1",
status="invalid"
)
def test_update_task_past_due_date(self):
# Past due date
past_date = datetime.datetime.now() - datetime.timedelta(days=1)
with self.assertRaises(InvalidDueDateError):
self.task_manager.update_task(
task_id=self.task.task_id,
caller_id="user1",
due_date=past_date
)
def test_update_task_completed_status(self):
# Set status to COMPLETED
self.task_manager.update_task(
task_id=self.task.task_id,
caller_id="user1",
status=TaskStatus.COMPLETED.value
)
updated_task = self.task_manager.storage.get_task(self.task.task_id)
self.assertEqual(updated_task.status, TaskStatus.COMPLETED)
self.assertIsNotNone(updated_task.completed_at)
def test_delete_task_valid_creator(self):
# Creator deletes task
self.task_manager.delete_task(self.task.task_id, "user1")
self.assertIsNone(self.task_manager.storage.get_task(self.task.task_id))
def test_delete_task_valid_admin(self):
# Admin deletes task
self.task_manager.delete_task(self.task.task_id, "admin1")
self.assertIsNone(self.task_manager.storage.get_task(self.task.task_id))
def test_delete_task_unauthorized(self):
# Non-creator, non-admin tries to delete
self.user_manager.is_user_valid.side_effect = lambda user_id: user_id in ["user1", "user2"]
self.user_manager.is_admin.side_effect = lambda user_id: False
with self.assertRaises(PermissionDeniedError):
self.task_manager.delete_task(self.task.task_id, "user2")
def test_delete_task_nonexistent(self):
# Non-existent task
with self.assertRaises(InvalidTaskError):
self.task_manager.delete_task("nonexistent", "user1")
def test_archive_task_valid_creator(self):
# Creator archives completed task
self.task_manager.update_task(self.task.task_id, "user1", status=TaskStatus.COMPLETED.value)
self.task_manager.archive_task(self.task.task_id, "user1")
task = self.task_manager.storage.get_task(self.task.task_id)
self.assertTrue(task.archived)
def test_archive_task_valid_admin(self):
# Admin archives completed task
self.task_manager.update_task(self.task.task_id, "admin1", status=TaskStatus.COMPLETED.value)
self.task_manager.archive_task(self.task.task_id, "admin1")
task = self.task_manager.storage.get_task(self.task.task_id)
self.assertTrue(task.archived)
def test_archive_task_unauthorized(self):
# Non-creator, non-admin tries to archive
self.user_manager.is_user_valid.side_effect = lambda user_id: user_id in ["user1", "user2"]
self.user_manager.is_admin.side_effect = lambda user_id: False
self.task_manager.update_task(self.task.task_id, "user1", status=TaskStatus.COMPLETED.value)
with self.assertRaises(PermissionDeniedError):
self.task_manager.archive_task(self.task.task_id, "user2")
def test_archive_task_nonexistent(self):
# Non-existent task
with self.assertRaises(InvalidTaskError):
self.task_manager.archive_task("nonexistent", "user1")
def test_archive_task_not_completed(self):
# Task not in COMPLETED status
with self.assertRaises(InvalidTaskError):
self.task_manager.archive_task(self.task.task_id, "user1")
def test_assign_task_valid_creator(self):
# Creator assigns task to valid users
self.task_manager.assign_task(self.task.task_id, "user1", ["user1", "admin1"])
task = self.task_manager.storage.get_task(self.task.task_id)
self.assertEqual(task.assignees, ["user1", "admin1"])
self.assertIsNotNone(task.assignment_time)
def test_assign_task_valid_admin(self):
# Admin assigns task to valid users
self.task_manager.assign_task(self.task.task_id, "admin1", ["user1", "admin1"])
task = self.task_manager.storage.get_task(self.task.task_id)
self.assertEqual(task.assignees, ["user1", "admin1"])
self.assertIsNotNone(task.assignment_time)
def test_assign_task_unauthorized(self):
# Non-creator, non-admin tries to assign
self.user_manager.is_user_valid.side_effect = lambda user_id: user_id in ["user1", "user2"]
self.user_manager.is_admin.side_effect = lambda user_id: False
with self.assertRaises(PermissionDeniedError):
self.task_manager.assign_task(self.task.task_id, "user2", ["user1"])
def test_assign_task_invalid_user(self):
# Assign to non-existent user
with self.assertRaises(InvalidUserError):
self.task_manager.assign_task(self.task.task_id, "user1", ["nonexistent"])
def test_assign_task_empty_assignees(self):
# Empty assignee list
self.task_manager.assign_task(self.task.task_id, "user1", [])
task = self.task_manager.storage.get_task(self.task.task_id)
self.assertEqual(task.assignees, [])
self.assertIsNotNone(task.assignment_time)
def test_assign_task_nonexistent_task(self):
# Non-existent task
with self.assertRaises(InvalidTaskError):
self.task_manager.assign_task("nonexistent", "user1", ["user1"])
if __name__ == '__main__':
unittest.main()
`
模块三
`
import unittest
from unittest.mock import Mock
from datetime import datetime, timedelta
import re
from typing import List, Optional, Dict, Any
# Import classes from task_manager and user_manager
from task_manager import (
TaskManager, Task, TaskStatus, TaskPriority,
InvalidTaskError, InvalidUserError, MemoryTaskStorage
)
from user_manager import UserManager, PermissionDeniedError, UserNotFoundError
from task_query_manager import TaskQueryManager
# Mock Role enum for user manager
class Role:
USER = "USER"
ADMIN = "ADMIN"
# Mock User class for testing
class User:
def __init__(self, user_id: str, role: Role):
self.user_id = user_id
self.role = role
# Test cases for boundary condition coverage
class TestTaskQueryManager(unittest.TestCase):
def setUp(self):
# Mock UserManager
self.user_manager = Mock(spec=UserManager)
self.user_manager.is_user_valid.side_effect = lambda user_id: user_id in ["user1", "user2", "admin1"]
self.user_manager.is_admin.side_effect = lambda user_id: user_id == "admin1"
# Mock TaskManager with MemoryTaskStorage
self.task_manager = TaskManager(self.user_manager, MemoryTaskStorage())
# Initialize TaskQueryManager
self.query_manager = TaskQueryManager(self.task_manager, self.user_manager)
# Create sample users
self.user1 = User("user1", Role.USER)
self.user2 = User("user2", Role.USER)
self.admin1 = User("admin1", Role.ADMIN)
# Create date references
self.now = datetime.now()
self.past_date = self.now - timedelta(days=1)
self.future_date = self.now + timedelta(days=5)
# Create sample tasks
self.task1 = self.task_manager.create_task(
title="Task 1",
creator_id="user1",
due_date=self.future_date,
description="Description 1",
priority=TaskPriority.HIGH.value
)
self.task2 = self.task_manager.create_task(
title="Task 2 meeting",
creator_id="user2",
due_date=self.past_date,
description="Description 2",
priority=TaskPriority.MEDIUM.value
)
self.task_manager.assign_task(self.task1.task_id, "user1", ["user1", "user2"])
self.task_manager.update_task(self.task2.task_id, "user2", status=TaskStatus.COMPLETED.value)
def test_query_tasks_valid_admin_all_tasks(self):
# Admin queries all tasks
result = self.query_manager.query_tasks(
caller_id="admin1",
page=1,
page_size=10,
sort_by="due_date",
sort_order="asc"
)
self.assertEqual(result["total"], 2)
self.assertEqual(len(result["tasks"]), 2)
self.assertEqual(result["tasks"][0]["task_id"], self.task2.task_id) # Past date first
self.assertEqual(result["page"], 1)
self.assertEqual(result["total_pages"], 1)
def test_query_tasks_valid_user_own_tasks(self):
# User queries own tasks (creator or assignee)
result = self.query_manager.query_tasks(
caller_id="user1",
page=1,
page_size=10,
sort_by="due_date",
sort_order="asc"
)
self.assertEqual(result["total"], 1)
self.assertEqual(len(result["tasks"]), 1)
self.assertEqual(result["tasks"][0]["task_id"], self.task1.task_id)
def test_query_tasks_invalid_caller(self):
# Invalid caller ID
with self.assertRaises(InvalidUserError):
self.query_manager.query_tasks(caller_id="invalid_user")
def test_query_tasks_invalid_page(self):
# Negative or zero page
with self.assertRaises(ValueError):
self.query_manager.query_tasks(caller_id="admin1", page=0)
with self.assertRaises(ValueError):
self.query_manager.query_tasks(caller_id="admin1", page=-1)
def test_query_tasks_invalid_page_size(self):
# Negative or zero page_size
with self.assertRaises(ValueError):
self.query_manager.query_tasks(caller_id="admin1", page_size=0)
with self.assertRaises(ValueError):
self.query_manager.query_tasks(caller_id="admin1", page_size=-1)
def test_query_tasks_invalid_sort_by(self):
# Invalid sort_by
with self.assertRaises(ValueError):
self.query_manager.query_tasks(caller_id="admin1", sort_by="invalid")
def test_query_tasks_invalid_sort_order(self):
# Invalid sort_order
with self.assertRaises(ValueError):
self.query_manager.query_tasks(caller_id="admin1", sort_order="invalid")
def test_query_tasks_invalid_status(self):
# Invalid status
with self.assertRaises(InvalidTaskError):
self.query_manager.query_tasks(caller_id="admin1", status="invalid")
def test_query_tasks_invalid_priority(self):
# Invalid priority
with self.assertRaises(InvalidTaskError):
self.query_manager.query_tasks(caller_id="admin1", priority="invalid")
def test_query_tasks_invalid_assignee(self):
# Invalid assignee ID
with self.assertRaises(InvalidUserError):
self.query_manager.query_tasks(caller_id="admin1", assignee_id="invalid_user")
def test_query_tasks_by_status(self):
# Filter by status (COMPLETED)
result = self.query_manager.query_tasks(
caller_id="admin1",
status=TaskStatus.COMPLETED.value
)
self.assertEqual(result["total"], 1)
self.assertEqual(result["tasks"][0]["task_id"], self.task2.task_id)
def test_query_tasks_by_priority(self):
# Filter by priority (HIGH)
result = self.query_manager.query_tasks(
caller_id="admin1",
priority=TaskPriority.HIGH.value
)
self.assertEqual(result["total"], 1)
self.assertEqual(result["tasks"][0]["task_id"], self.task1.task_id)
def test_query_tasks_by_assignee(self):
# Filter by assignee
result = self.query_manager.query_tasks(
caller_id="admin1",
assignee_id="user2"
)
self.assertEqual(result["total"], 1)
self.assertEqual(result["tasks"][0]["task_id"], self.task1.task_id)
def test_query_tasks_by_due_date_range(self):
# Filter by due date range
result = self.query_manager.query_tasks(
caller_id="admin1",
due_date_start=self.now,
due_date_end=self.future_date + timedelta(days=1)
)
self.assertEqual(result["total"], 1)
self.assertEqual(result["tasks"][0]["task_id"], self.task1.task_id)
def test_query_tasks_by_keyword(self):
# Filter by keyword in title
result = self.query_manager.query_tasks(
caller_id="admin1",
keyword="meeting"
)
self.assertEqual(result["total"], 1)
self.assertEqual(result["tasks"][0]["task_id"], self.task2.task_id)
def test_query_tasks_empty_result(self):
# Filter with no matching tasks
result = self.query_manager.query_tasks(
caller_id="admin1",
keyword="nonexistent"
)
self.assertEqual(result["total"], 0)
self.assertEqual(result["tasks"], [])
self.assertEqual(result["total_pages"], 0)
self.assertEqual(result["message"], "No tasks found")
def test_query_tasks_pagination(self):
# Pagination with multiple tasks
for i in range(3, 13): # Create 10 more tasks
self.task_manager.create_task(
title=f"Task {i}",
creator_id="user1",
due_date=self.future_date + timedelta(days=i),
priority=TaskPriority.MEDIUM.value
)
result = self.query_manager.query_tasks(
caller_id="admin1",
page=2,
page_size=5,
sort_by="due_date",
sort_order="asc"
)
self.assertEqual(result["total"], 12)
self.assertEqual(len(result["tasks"]), 5)
self.assertEqual(result["page"], 2)
self.assertEqual(result["total_pages"], 3)
def test_query_tasks_pagination_last_page(self):
# Last page with fewer tasks
for i in range(3, 8): # Create 5 more tasks
self.task_manager.create_task(
title=f"Task {i}",
creator_id="user1",
due_date=self.future_date + timedelta(days=i)
)
result = self.query_manager.query_tasks(
caller_id="admin1",
page=2,
page_size=5
)
self.assertEqual(result["total"], 7)
self.assertEqual(len(result["tasks"]), 2)
self.assertEqual(result["total_pages"], 2)
def test_query_tasks_sort_by_priority_desc(self):
# Sort by priority descending
result = self.query_manager.query_tasks(
caller_id="admin1",
sort_by="priority",
sort_order="desc"
)
self.assertEqual(result["total"], 2)
self.assertEqual(result["tasks"][0]["task_id"], self.task1.task_id) # HIGH first
self.assertEqual(result["tasks"][1]["task_id"], self.task2.task_id) # MEDIUM second
def test_get_task_details_valid_creator(self):
# Creator accesses task details
details = self.query_manager.get_task_details(self.task1.task_id, "user1")
self.assertEqual(details["task_id"], self.task1.task_id)
self.assertEqual(details["creator_id"], "user1")
def test_get_task_details_valid_assignee(self):
# Assignee accesses task details
details = self.query_manager.get_task_details(self.task1.task_id, "user2")
self.assertEqual(details["task_id"], self.task1.task_id)
def test_get_task_details_valid_admin(self):
# Admin accesses task details
details = self.query_manager.get_task_details(self.task1.task_id, "admin1")
self.assertEqual(details["task_id"], self.task1.task_id)
def test_get_task_details_invalid_caller(self):
# Invalid caller ID
with self.assertRaises(InvalidUserError):
self.query_manager.get_task_details(self.task1.task_id, "invalid_user")
def test_get_task_details_unauthorized(self):
# Non-creator, non-assignee, non-admin tries to access
self.user_manager.is_user_valid.side_effect = lambda user_id: user_id in ["user1", "user2", "user3"]
self.user_manager.is_admin.side_effect = lambda user_id: False
with self.assertRaises(PermissionDeniedError):
self.query_manager.get_task_details(self.task1.task_id, "user3")
def test_get_task_details_nonexistent_task(self):
# Non-existent task
with self.assertRaises(InvalidTaskError):
self.query_manager.get_task_details("nonexistent", "admin1")
def test_count_incomplete_tasks_valid_self(self):
# User counts own incomplete tasks
count = self.query_manager.count_incomplete_tasks("user1", "user1")
self.assertEqual(count, 1) # task1 is TODO
def test_count_incomplete_tasks_valid_admin(self):
# Admin counts user's incomplete tasks
count = self.query_manager.count_incomplete_tasks("user1", "admin1")
self.assertEqual(count, 1)
def test_count_incomplete_tasks_invalid_user(self):
# Invalid user ID
with self.assertRaises(InvalidUserError):
self.query_manager.count_incomplete_tasks("invalid_user", "admin1")
def test_count_incomplete_tasks_invalid_caller(self):
# Invalid caller ID
with self.assertRaises(InvalidUserError):
self.query_manager.count_incomplete_tasks("user1", "invalid_user")
def test_count_incomplete_tasks_unauthorized(self):
# Non-admin, non-self tries to count
self.user_manager.is_user_valid.side_effect = lambda user_id: user_id in ["user1", "user2"]
self.user_manager.is_admin.side_effect = lambda user_id: False
with self.assertRaises(PermissionDeniedError):
self.query_manager.count_incomplete_tasks("user1", "user2")
def test_count_incomplete_tasks_no_incomplete(self):
# User with no incomplete tasks
self.task_manager.update_task(self.task1.task_id, "user1", status=TaskStatus.COMPLETED.value)
count = self.query_manager.count_incomplete_tasks("user1", "user1")
self.assertEqual(count, 0)
if __name__ == '__main__':
unittest.main()
`
模块四
`
import unittest
from unittest.mock import Mock, patch, AsyncMock
import asyncio
from datetime import datetime, timedelta
from typing import List, Optional, Dict
from notification_service import (
NotificationService, Notification, NotificationType, Priority, NotificationStatus,
NotificationSettings, TaskDetails, UserContact
)
# Mock TaskManager and UserManager interfaces
class MockTaskManager:
def get_task_details(self, task_id: int) -> TaskDetails:
if task_id == 1:
return TaskDetails(
task_id=1,
title="Test Task",
assignees=[1, 2],
creator_id=3,
deadline=datetime.now() + timedelta(days=1)
)
raise ValueError("Task not found")
class MockUserManager:
def __init__(self):
self.settings = {
1: NotificationSettings(user_id=1, receive_task_assigned=True, receive_status_changed=True, receive_deadline_approaching=True),
2: NotificationSettings(user_id=2, receive_task_assigned=False, receive_status_changed=True, receive_deadline_approaching=True),
3: NotificationSettings(user_id=3, receive_task_assigned=True, receive_status_changed=False, receive_deadline_approaching=True)
}
self.contacts = {
1: UserContact(user_id=1, email="user1@example.com"),
2: UserContact(user_id=2, email="user2@example.com"),
3: UserContact(user_id=3, email="user3@example.com")
}
def get_notification_settings(self, user_id: int) -> NotificationSettings:
if user_id not in self.settings:
raise ValueError("User not found")
return self.settings[user_id]
def update_notification_settings(self, user_id: int, settings: NotificationSettings) -> None:
if user_id not in self.settings:
raise ValueError("User not found")
self.settings[user_id] = settings
def get_user_contact(self, user_id: int) -> UserContact:
if user_id not in self.contacts:
raise ValueError("User not found")
return self.contacts[user_id]
# Test cases for boundary condition coverage
class TestNotificationService(unittest.TestCase):
def setUp(self):
# Mock dependencies
self.task_manager = MockTaskManager()
self.user_manager = MockUserManager()
self.smtp_config = {
"host": "smtp.example.com",
"port": 587,
"user": "test_user",
"password": "test_password",
"from_email": "no-reply@taskmanager.com"
}
self.service = NotificationService(self.task_manager, self.user_manager, self.smtp_config)
self.loop = asyncio.get_event_loop()
@patch('notification_service.smtplib.SMTP')
def test_handle_task_assigned_valid(self, mock_smtp):
# Valid task assignment, high priority, email success
mock_smtp.return_value.__enter__.return_value.login.return_value = None
mock_smtp.return_value.__enter__.return_value.send_message.return_value = None
self.service.handle_task_assigned(task_id=1, user_ids=[1, 2])
self.assertEqual(len(self.service.notifications), 2)
self.assertEqual(self.service.notifications[0].user_id, 1)
self.assertEqual(self.service.notifications[0].notification_type, NotificationType.TASK_ASSIGNED)
self.assertEqual(self.service.notifications[0].priority, Priority.HIGH)
self.assertEqual(self.service.notifications[0].status, NotificationStatus.SUCCESS)
self.assertEqual(self.service.notifications[1].user_id, 2)
self.assertEqual(self.service.notifications[1].status, NotificationStatus.FAILED)
self.assertEqual(self.service.notifications[1].failure_reason, "用户已关闭此类型通知")
@patch('notification_service.smtplib.SMTP')
def test_handle_task_assigned_empty_user_ids(self, mock_smtp):
# Empty user IDs list
self.service.handle_task_assigned(task_id=1, user_ids=[])
self.assertEqual(len(self.service.notifications), 0)
@patch('notification_service.smtplib.SMTP')
def test_handle_task_assigned_email_failure(self, mock_smtp):
# High-priority email failure
mock_smtp.return_value.__enter__.return_value.login.side_effect = Exception("SMTP error")
self.service.handle_task_assigned(task_id=1, user_ids=[1])
self.assertEqual(len(self.service.notifications), 1)
self.assertEqual(self.service.notifications[0].status, NotificationStatus.FAILED)
self.assertTrue(self.service.notifications[0].failure_reason.startswith("邮件发送失败"))
@patch('notification_service.smtplib.SMTP')
def test_handle_status_changed_valid(self, mock_smtp):
# Valid status change, low priority, queued
self.service.handle_status_changed(task_id=1, new_status="completed")
self.assertEqual(len(self.service.notifications), 3) # Creator (3) and assignees (1, 2)
self.assertEqual(self.service.notifications[0].user_id, 1)
self.assertEqual(self.service.notifications[0].notification_type, NotificationType.STATUS_CHANGED)
self.assertEqual(self.service.notifications[0].priority, Priority.LOW)
self.assertEqual(self.service.notifications[0].status, NotificationStatus.SUCCESS)
self.assertEqual(self.service.notifications[1].user_id, 2)
self.assertEqual(self.service.notifications[2].user_id, 3)
self.assertEqual(self.service.notifications[2].status, NotificationStatus.FAILED)
self.assertEqual(self.service.notifications[2].failure_reason, "用户已关闭此类型通知")
def test_handle_status_changed_invalid_task(self):
# Invalid task ID
self.task_manager.get_task_details = Mock(side_effect=ValueError("Task not found"))
self.service.handle_status_changed(task_id=999, new_status="completed")
self.assertEqual(len(self.service.notifications), 0)
@patch('notification_service.smtplib.SMTP')
def test_handle_deadline_approaching_valid(self, mock_smtp):
# Valid deadline approaching, low priority, queued
deadline = datetime.now() + timedelta(days=1)
self.service.handle_deadline_approaching(task_id=1, deadline=deadline)
self.assertEqual(len(self.service.notifications), 3) # Creator (3) and assignees (1, 2)
self.assertEqual(self.service.notifications[0].notification_type, NotificationType.DEADLINE_APPROACHING)
self.assertEqual(self.service.notifications[0].priority, Priority.LOW)
self.assertEqual(self.service.notifications[0].status, NotificationStatus.SUCCESS)
self.assertTrue("将于" in self.service.notifications[0].content)
def test_handle_deadline_approaching_invalid_task(self):
# Invalid task ID
self.task_manager.get_task_details = Mock(side_effect=ValueError("Task not found"))
self.service.handle_deadline_approaching(task_id=999, deadline=datetime.now())
self.assertEqual(len(self.service.notifications), 0)
def test_get_notification_history_valid(self):
# Valid history within 7 days
self.service.handle_task_assigned(task_id=1, user_ids=[1])
history = self.service.get_notification_history(user_id=1, days=7)
self.assertEqual(len(history), 1)
self.assertEqual(history[0].user_id, 1)
def test_get_notification_history_no_notifications(self):
# No notifications for user
history = self.service.get_notification_history(user_id=1, days=7)
self.assertEqual(len(history), 0)
def test_get_notification_history_old_notifications(self):
# Notifications older than cutoff
old_notification = Notification(
notification_id=1,
task_id=1,
user_id=1,
notification_type=NotificationType.TASK_ASSIGNED,
priority=Priority.HIGH,
content="Old notification",
send_time=datetime.now() - timedelta(days=8),
status=NotificationStatus.SUCCESS
)
self.service.notifications.append(old_notification)
history = self.service.get_notification_history(user_id=1, days=7)
self.assertEqual(len(history), 0)
def test_get_notification_history_zero_days(self):
# Days = 0 (no notifications)
self.service.handle_task_assigned(task_id=1, user_ids=[1])
history = self.service.get_notification_history(user_id=1, days=0)
self.assertEqual(len(history), 0)
def test_update_notification_settings_valid(self):
# Valid settings update
new_settings = NotificationSettings(
user_id=1,
receive_task_assigned=False,
receive_status_changed=False,
receive_deadline_approaching=False
)
self.service.update_notification_settings(user_id=1, settings=new_settings)
updated_settings = self.user_manager.get_notification_settings(1)
self.assertFalse(updated_settings.receive_task_assigned)
self.assertFalse(updated_settings.receive_status_changed)
self.assertFalse(updated_settings.receive_deadline_approaching)
def test_update_notification_settings_invalid_user(self):
# Invalid user ID
new_settings = NotificationSettings(user_id=999, receive_task_assigned=True)
with self.assertRaises(ValueError):
self.service.update_notification_settings(user_id=999, settings=new_settings)
def test_get_notification_settings_valid(self):
# Valid settings retrieval
settings = self.service.get_notification_settings(user_id=1)
self.assertEqual(settings.user_id, 1)
self.assertTrue(settings.receive_task_assigned)
self.assertTrue(settings.receive_status_changed)
self.assertTrue(settings.receive_deadline_approaching)
def test_get_notification_settings_invalid_user(self):
# Invalid user ID
with self.assertRaises(ValueError):
self.service.get_notification_settings(user_id=999)
@patch('notification_service.smtplib.SMTP')
def test_send_notification_site_message_failure(self, mock_smtp):
# Site message failure
with patch.object(self.service, '_send_site_message', return_value=False):
notification = self.service._send_notification(
user_id=1,
task_id=1,
notification_type=NotificationType.TASK_ASSIGNED,
priority=Priority.HIGH
)
self.assertEqual(notification.status, NotificationStatus.FAILED)
self.assertEqual(notification.failure_reason, "站内消息发送失败")
@patch('notification_service.smtplib.SMTP')
async def test_send_email_async_success(self, mock_smtp):
# Email success
mock_smtp.return_value.__enter__.return_value.login.return_value = None
mock_smtp.return_value.__enter__.return_value.send_message
`
模块五
`
```python
import unittest
from unittest.mock import patch, Mock, mock_open
import sqlite3
from datetime import datetime
import json
import os
from typing import List, Dict
from system_config import SystemConfig, AuditLog, DataBackup, NotificationType, TaskPriority
class TestSystemConfigAuditBackup(unittest.TestCase):
def setUp(self):
# Mock SQLite connection and cursor
self.mock_conn = Mock()
self.mock_cursor = Mock()
self.mock_conn.cursor.return_value = self.mock_cursor
self.mock_conn.__enter__.return_value = self.mock_conn
self.mock_conn.__exit__.return_value = None
self.db_path = "task_management.db"
self.backup_dir = "backups"
# Patch sqlite3.connect
self.sqlite_patch = patch('sqlite3.connect', return_value=self.mock_conn)
self.sqlite_patch.start()
# Patch os.makedirs
self.makedirs_patch = patch('os.makedirs')
self.makedirs_patch.start()
# Initialize classes
self.system_config = SystemConfig()
self.audit_log = AuditLog(self.db_path)
self.data_backup = DataBackup(self.db_path)
def tearDown(self):
# Stop patches
self.sqlite_patch.stop()
self.makedirs_patch.stop()
def test_system_config_init_db_success(self):
# Successful database initialization
self.mock_cursor.execute.reset_mock()
self.system_config._init_db()
self.mock_cursor.execute.assert_called_once()
self.assertEqual(self.system_config._db_path, "task_management.db")
@patch('system_config.logging.error')
def test_system_config_init_db_failure(self, mock_log_error):
# Database initialization failure
self.mock_conn.cursor.side_effect = sqlite3.Error("DB error")
with self.assertRaises(sqlite3.Error):
self.system_config._init_db()
mock_log_error.assert_called_with("Database connection failed: DB error")
def test_update_notification_type_valid(self):
# Valid notification types
for ntype in [NotificationType.EMAIL.value, NotificationType.IN_APP.value, NotificationType.SMS.value]:
with self.subTest(ntype=ntype):
result = self.system_config.update_notification_type(ntype)
self.assertTrue(result)
self.assertEqual(self.system_config._config["notification_type"], ntype)
@patch('system_config.logging.warning')
def test_update_notification_type_invalid(self, mock_log_warning):
# Invalid notification type
result = self.system_config.update_notification_type("invalid")
self.assertFalse(result)
self.assertEqual(self.system_config._config["notification_type"], NotificationType.IN_APP.value)
mock_log_warning.assert_called_with("Invalid notification type: invalid")
def test_update_default_priority_valid(self):
# Valid priorities
for priority in [TaskPriority.LOW.value, TaskPriority.MEDIUM.value, TaskPriority.HIGH.value]:
with self.subTest(priority=priority):
result = self.system_config.update_default_priority(priority)
self.assertTrue(result)
self.assertEqual(self.system_config._config["default_priority"], priority)
@patch('system_config.logging.warning')
def test_update_default_priority_invalid(self, mock_log_warning):
# Invalid priority
result = self.system_config.update_default_priority("invalid")
self.assertFalse(result)
self.assertEqual(self.system_config._config["default_priority"], TaskPriority.MEDIUM.value)
mock_log_warning.assert_called_with("Invalid priority: invalid")
def test_add_task_status_valid(self):
# Valid new status
result = self.system_config.add_task_status("Blocked")
self.assertTrue(result)
self.assertIn("Blocked", self.system_config._config["task_statuses"])
@patch('system_config.logging.warning')
def test_add_task_status_empty(self, mock_log_warning):
# Empty or blank status
for status in ["", " "]:
with self.subTest(status=status):
result = self.system_config.add_task_status(status)
self.assertFalse(result)
self.assertNotIn(status, self.system_config._config["task_statuses"])
mock_log_warning.assert_called_with("Task status cannot be empty")
@patch('system_config.logging.warning')
def test_add_task_status_duplicate(self, mock_log_warning):
# Duplicate status
self.system_config._config["task_statuses"] = ["To Do"]
result = self.system_config.add_task_status("To Do")
self.assertFalse(result)
self.assertEqual(self.system_config._config["task_statuses"].count("To Do"), 1)
mock_log_warning.assert_called_with("Task status 'To Do' already exists")
def test_get_config(self):
# Get configuration
config = self.system_config.get_config()
expected = {
"notification_type": NotificationType.IN_APP.value,
"default_priority": TaskPriority.MEDIUM.value,
"task_statuses": ["To Do", "In Progress", "Done"]
}
self.assertEqual(config, expected)
# Verify deep copy
config["task_statuses"].append("Blocked")
self.assertNotIn("Blocked", self.system_config._config["task_statuses"])
def test_audit_log_log_action_success(self):
# Successful log action
self.mock_cursor.execute.reset_mock()
self.audit_log.log_action(task_id="task1", action="create", user_id="user1", details="Task created")
self.mock_cursor.execute.assert_called_once()
args = self.mock_cursor.execute.call_args[0]
self.assertEqual(args[0], "INSERT INTO audit_logs (task_id, action, user_id, timestamp, details) VALUES (?, ?, ?, ?, ?)")
self.assertEqual(args[1][:3], ("task1", "create", "user1"))
@patch('system_config.logging.error')
def test_audit_log_log_action_failure(self, mock_log_error):
# Database failure
self.mock_cursor.execute.side_effect = sqlite3.Error("DB error")
self.audit_log.log_action(task_id="task1", action="create", user_id="user1")
mock_log_error.assert_called_with("Failed to log action: DB error")
def test_audit_log_get_task_history_success(self):
# Successful retrieval
self.mock_cursor.fetchall.return_value = [
(1, "task1", "create", "user1", "2025-05-30T12:00:00", "Task created"),
(2, "task1", "update", "user2", "2025-05-30T12:01:00", "Status updated")
]
history = self.audit_log.get_task_history("task1")
self.assertEqual(len(history), 2)
self.assertEqual(history[0]["task_id"], "task1")
self.assertEqual(history[0]["action"], "create")
self.assertEqual(history[1]["user_id"], "user2")
def test_audit_log_get_task_history_empty(self):
# No logs for task
self.mock_cursor.fetchall.return_value = []
history = self.audit_log.get_task_history("task1")
self.assertEqual(history, [])
@patch('system_config.logging.error')
def test_audit_log_get_task_history_failure(self, mock_log_error):
# Database failure
self.mock_cursor.execute.side_effect = sqlite3.Error("DB error")
history = self.audit_log.get_task_history("task1")
self.assertEqual(history, [])
mock_log_error.assert_called_with("Failed to retrieve task history: DB error")
@patch('builtins.open', new_callable=mock_open)
def test_data_backup_success(self, mock_file):
# Successful backup
self.mock_cursor.fetchall.return_value = [
(1, "task1", "create", "user1", "2025-05-30T12:00:00", "Task created")
]
backup_file = self.data_backup.backup()
self.assertIsNotNone(backup_file)
self.assertTrue(backup_file.startswith("backups/backup_"))
self.assertTrue(backup_file.endswith(".json"))
mock_file.assert_called_once()
written_data = json.loads(mock_file().write.call_args[0][0])
self.assertEqual(len(written_data), 1)
self.assertEqual(written_data[0]["task_id"], "task1")
@patch('system_config.logging.error')
def test_data_backup_db_failure(self, mock_log_error):
# Database failure
self.mock_cursor.fetchall.side_effect = sqlite3.Error("DB error")
result = self.data_backup.backup()
self.assertIsNone(result)
mock_log_error.assert_called_with("Backup failed: DB error")
@patch('system_config.logging.error')
@patch('builtins.open', side_effect=OSError("File error"))
def test_data_backup_file_failure(self, mock_open, mock_log_error):
# File system failure
self.mock_cursor.fetchall.return_value = []
result = self.data_backup.backup()
self.assertIsNone(result)
mock_log_error.assert_called_with("Backup failed: File error")
@patch('builtins.open', new_callable=mock_open)
def test_data_restore_success(self, mock_file):
# Successful restore
backup_data = [
{"id": 1, "task_id": "task1", "action": "create", "user_id": "user1", "timestamp": "2025-05-30T12:00:00", "details": "Task created"}
]
mock_file().read.return_value = json.dumps(backup_data)
self.mock_cursor.execute.reset_mock()
result = self.data_backup.restore("backups/backup_test.json")
self.assertTrue(result)
self.mock_cursor.execute.assert_any_call("DELETE FROM audit_logs")
self.mock_cursor.execute.assert_any_call(
"INSERT INTO audit_logs (id, task_id, action, user_id, timestamp, details) VALUES (?, ?, ?, ?, ?, ?)",
(1, "task1", "create", "user1", "2025-05-30T12:00:00", "Task created")
)
@patch('system_config.logging.error')
@patch('builtins.open', new_callable=mock_open)
def test_data_restore_invalid_json(self, mock_file, mock_log_error):
# Invalid JSON in backup file
mock_file().read.return_value = "invalid json"
result = self.data_backup.restore("backups/backup_test.json")
self.assertFalse(result)
mock_log_error.assert_called_with("Restore failed: Expecting value: line 1 column 1 (char 0)")
@patch('system_config.logging.error')
@patch('builtins.open', side_effect=OSError("File not found"))
def test_data_restore_file_not_found(self, mock_open, mock_log_error):
# Non-existent backup file
result = self.data_backup.restore("backups/nonexistent.json")
self.assertFalse(result)
mock_log_error.assert_called_with("Restore failed: File not found")
@patch('system_config.logging.error')
def test_data_restore_db_failure(self, mock_log_error):
# Database failure during restore
self.mock_cursor.execute.side_effect = sqlite3.Error("DB error")
with patch('builtins.open', mock_open(read_data=json.dumps([]))):
result = self.data_backup.restore("backups/backup_test.json")
self.assertFalse(result)
mock_log_error.assert_called_with("Restore failed: DB error")
if __name__ == '__main__':
unittest.main()
`
a-zA-Z0-9._%+- ↩︎
浙公网安备 33010602011771号