Skip to content

Commit

Permalink
Improve test coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
yihong1120 committed Dec 21, 2024
1 parent 290c266 commit fe09b5b
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 2 deletions.
1 change: 1 addition & 0 deletions examples/YOLO_server_api/backend/routers.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,7 @@ async def model_file_update(

# Check if the path is within the intended directory
if not temp_path.resolve().parent == temp_dir:
logger.error(f"Invalid file path detected: {temp_path}")
raise HTTPException(status_code=400, detail='Invalid file path.')

# Write file to disk
Expand Down
52 changes: 52 additions & 0 deletions tests/examples/YOLO_server_api/backend/auth_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,58 @@ async def test_create_token_user_in_cache(self) -> None:
self.assertEqual(response.json()['access_token'], 'mocked_token')
self.mock_db.execute.assert_not_called()

async def test_create_token_user_inactive(self) -> None:
"""
Test token creation failure when the user account is inactive.
"""
# Set the mock user to inactive
self.mock_user.is_active = False

# Mock the database execute result to return the user
mock_result = MagicMock()
mock_result.scalar.return_value = self.mock_user
self.mock_db.execute.return_value = mock_result

# Send a POST request with valid credentials
response = await self.aclient.post(
'/api/token', json={
'username': self.username,
'password': self.password,
},
)

# Assert the response indicates the account is inactive
self.assertEqual(response.status_code, 403)
self.assertEqual(
response.json()['detail'], 'User account is inactive',
)

async def test_create_token_invalid_role(self) -> None:
"""
Test token creation failure when the user role is invalid.
"""
# Set the mock user to have an invalid role
self.mock_user.role = 'invalid_role'

# Mock the database execute result to return the user
mock_result = MagicMock()
mock_result.scalar.return_value = self.mock_user
self.mock_db.execute.return_value = mock_result

# Send a POST request with valid credentials
response = await self.aclient.post(
'/api/token', json={
'username': self.username,
'password': self.password,
},
)

# Assert the response indicates the role is invalid
self.assertEqual(response.status_code, 403)
self.assertEqual(
response.json()['detail'], 'User does not have the required role',
)


if __name__ == '__main__':
unittest.main()
43 changes: 43 additions & 0 deletions tests/examples/YOLO_server_api/backend/detection_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,49 @@ async def test_check_containment(self) -> None:
result = await check_containment(index1, index2, datas)
self.assertIsInstance(result, set)

async def test_remove_overlapping_labels_line_134(self) -> None:
"""
測試移除重疊的標籤,覆蓋到 datas.pop(index) 這一行。
"""
datas = [
[0, 0, 100, 100, 0.9, 0], # 'hardhat' 標籤
[0, 0, 100, 100, 0.8, 2], # 'no_hardhat' 標籤,完全重疊
[200, 200, 300, 300, 0.85, 7], # 'safety_vest' 標籤
[200, 200, 300, 300, 0.7, 4] # 'no_safety_vest' 標籤,完全重疊
]
result = await remove_overlapping_labels(datas.copy())
self.assertEqual(len(result), 2)
remaining_labels = [d[5] for d in result]
self.assertListEqual(remaining_labels, [0, 7])

async def test_remove_completely_contained_labels_line_340(self) -> None:
"""
測試移除完全包含的標籤,覆蓋到 datas.pop(index) 這一行。
"""
datas = [
[50, 50, 150, 150, 0.9, 0], # 'hardhat' 標籤
[70, 70, 130, 130, 0.8, 2], # 'no_hardhat' 標籤,完全包含在 'hardhat' 中
[200, 200, 300, 300, 0.85, 7], # 'safety_vest' 標籤
[220, 220, 280, 280, 0.7, 4] # 'no_safety_vest' 標籤,完全包含在 'safety_vest' 中
]
result = await remove_completely_contained_labels(datas.copy())
self.assertEqual(len(result), 2)
remaining_labels = [d[5] for d in result]
self.assertListEqual(remaining_labels, [0, 7])

async def test_check_containment_elif_condition(self) -> None:
"""
測試 `check_containment` 函數中的 `elif` 條件,覆蓋相應的代碼行。
"""
index1 = 0
index2 = 1
datas = [
[70, 70, 130, 130, 0.9, 1], # index1,被 index2 完全包含
[50, 50, 150, 150, 0.85, 2], # index2
]
result = await check_containment(index1, index2, datas)
self.assertSetEqual(result, {0})


if __name__ == '__main__':
unittest.main()
34 changes: 32 additions & 2 deletions tests/examples/YOLO_server_api/backend/routers_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,8 +398,9 @@ def test_model_file_update(self, mock_logger, mock_update_model_file):
"""
Test updating a model file with mocked update_model_file function.
"""
# Simulate successful execution
async def mock_update_model_file_func(model, temp_path):
pass # Simulate successful execution
pass
mock_update_model_file.side_effect = mock_update_model_file_func

model_file_content = b'model file content'
Expand Down Expand Up @@ -433,7 +434,7 @@ async def mock_update_model_file_func(model, temp_path):
)
self.assertEqual(response.status_code, 403)

# Invalid file path scenario
# Invalid file path scenario (ValueError)
with patch(
'examples.YOLO_server_api.backend.routers.secure_filename',
return_value='../model.pt',
Expand All @@ -443,6 +444,35 @@ async def mock_update_model_file_func(model, temp_path):
'/api/model_file_update', data=data, files=files,
)
self.assertEqual(response.status_code, 400)
mock_logger.error.assert_called()

# Simulate ValueError in update_model_file
async def mock_update_model_file_raise_value_error(model, temp_path):
raise ValueError('Invalid model')
mock_update_model_file.side_effect = mock_update_model_file_raise_value_error

with self.override_jwt_credentials({'role': 'admin', 'id': 1}):
response = self.client.post(
'/api/model_file_update', data=data, files=files,
)
self.assertEqual(response.status_code, 400)
self.assertEqual(response.json()['detail'], 'Invalid model')
mock_logger.error.assert_called_with(
'Model update validation error: Invalid model',
)

# Simulate OSError during file operation
with patch('pathlib.Path.open', side_effect=OSError('Disk error')):
mock_update_model_file.side_effect = mock_update_model_file_func # Reset side effect
with self.override_jwt_credentials({'role': 'admin', 'id': 1}):
response = self.client.post(
'/api/model_file_update', data=data, files=files,
)
self.assertEqual(response.status_code, 500)
self.assertEqual(response.json()['detail'], 'Disk error')
mock_logger.error.assert_called_with(
'Model update I/O error: Disk error',
)

@patch('examples.YOLO_server_api.backend.routers.get_new_model_file')
@patch('examples.YOLO_server_api.backend.routers.logger')
Expand Down

0 comments on commit fe09b5b

Please sign in to comment.