Skip to content

Commit 3a72530

Browse files
committed
Fixe unit test cases
1 parent cf1b107 commit 3a72530

File tree

4 files changed

+204
-41
lines changed

4 files changed

+204
-41
lines changed

.github/workflows/unit_tests.yaml

Lines changed: 31 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,42 @@
1-
---
21
name: Unit Tests
3-
4-
#############################
5-
# Start the job on all push #
6-
#############################
72
on:
3+
workflow_dispatch:
84
push:
95
branches-ignore:
106
- '**'
11-
# Remove the line above to run when pushing to master
127
pull_request:
13-
branches: [master, dev, stage]
8+
branches: [main, dev, stage]
149

15-
###############
16-
# Set the Job #
17-
###############
1810
jobs:
1911
UnitTest:
20-
name: Unit Test Cases
21-
# Set the agent to run on
2212
runs-on: ubuntu-latest
13+
14+
env:
15+
DATABASE_NAME: test_database
16+
2317
steps:
24-
- name: Checkout code
25-
uses: actions/checkout@v3
26-
27-
- name: Set up Python
28-
uses: actions/setup-python@v4
29-
with:
30-
python-version: "3.10" # Use the appropriate Python version
31-
32-
- name: Install dependencies
33-
run: |
34-
pip install -r requirements.txt
35-
36-
- name: Run unit tests
37-
run: |
38-
python test_report.py
39-
coverage run --source=src -m unittest discover -s tests/
40-
coverage report -m
41-
exit_status=$?
42-
43-
# Set the exit status as an output for later use
44-
echo "::set-output name=exit_status::$exit_status"
45-
46-
- name: Archive Coverage Report
47-
if: ${{ always() }} # Upload the coverage report even if tests fail
48-
uses: actions/upload-artifact@v2
49-
with:
50-
name: htmlcov
51-
path: htmlcov
18+
- name: Checkout code
19+
uses: actions/checkout@v2
20+
21+
- name: Set up Python
22+
uses: actions/setup-python@v2
23+
with:
24+
python-version: '3.10'
25+
26+
- name: Install dependencies
27+
run: |
28+
python -m pip install --upgrade pip
29+
pip install -r requirements.txt
30+
31+
- name: Run tests with coverage
32+
run: |
33+
coverage run --source=src -m unittest discover -s tests/unit_tests
34+
coverage xml
35+
36+
- name: Check coverage
37+
run: |
38+
coverage report --fail-under=85
39+
40+
41+
42+

src/osw_validator.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def validate(self, received_message: Upload):
5757
if self.has_permission(roles=['tdei-admin', 'poc', 'osw_data_generator'],
5858
queue_message=received_message) is None:
5959
error_msg = 'Unauthorized request !'
60-
logger.error(tdei_record_id, error_msg, received_message)
60+
logger.error(f'{tdei_record_id}, {error_msg}, {received_message}')
6161
raise Exception(error_msg)
6262

6363
file_upload_path = urllib.parse.unquote(received_message.data.file_upload_path)

tests/unit_tests/test_queue_message_content.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ def setUp(self):
1919
data = TEST_DATA
2020
self.upload = Upload(data)
2121

22+
def test_message(self):
23+
self.upload.message = 'New message'
24+
self.assertEqual(self.upload.message, 'New message')
25+
2226
def test_message_type(self):
2327
self.assertEqual(self.upload.message_type, 'workflow_identifier')
2428
self.upload.message_type = 'New messageType'

tests/unit_tests/test_service.py

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
import unittest
2+
from unittest.mock import patch, MagicMock
3+
from src.osw_validator import OSWValidator
4+
from src.models.queue_message_content import ValidationResult
5+
6+
7+
class TestOSWValidatorService(unittest.TestCase):
8+
9+
@patch('src.osw_validator.Settings')
10+
@patch('src.osw_validator.Core')
11+
def setUp(self, mock_core, mock_settings):
12+
# Mock Settings
13+
mock_settings.return_value.event_bus.upload_subscription = 'test_subscription'
14+
mock_settings.return_value.event_bus.upload_topic = 'test_request_topic'
15+
mock_settings.return_value.event_bus.validation_topic = 'test_response_topic'
16+
mock_settings.return_value.max_concurrent_messages = 10
17+
mock_settings.return_value.get_download_directory.return_value = '/tmp'
18+
mock_settings.return_value.event_bus.container_name = 'test_container'
19+
20+
# Mock Core
21+
mock_core.return_value.get_topic.return_value = MagicMock()
22+
mock_core.return_value.get_storage_client.return_value = MagicMock()
23+
24+
# Initialize OSWValidator with mocked dependencies
25+
self.service = OSWValidator()
26+
self.service.storage_client = MagicMock()
27+
self.service.container_name = 'test_container'
28+
self.auth = MagicMock()
29+
30+
# Define a sample message with proper strings
31+
self.sample_message = {
32+
'messageId': 'c8c76e89f30944d2b2abd2491bd95337', # messageId as string
33+
'messageType': 'workflow_identifier', # Ensure this is a string
34+
'data': {
35+
'file_upload_path': 'https://tdeisamplestorage.blob.core.windows.net/tdei-storage-test/Archivew.zip',
36+
'user_id': 'c59d29b6-a063-4249-943f-d320d15ac9ab',
37+
'tdei_project_group_id': '0b41ebc5-350c-42d3-90af-3af4ad3628fb'
38+
}
39+
}
40+
41+
@patch('src.osw_validator.QueueMessage')
42+
@patch('src.osw_validator.Upload')
43+
def test_subscribe_with_valid_message(self, mock_request_message, mock_queue_message):
44+
# Arrange
45+
mock_message = MagicMock()
46+
mock_queue_message.to_dict.return_value = self.sample_message
47+
mock_request_message.from_dict.return_value = mock_request_message
48+
self.service.validate = MagicMock()
49+
50+
# Act
51+
self.service.start_listening()
52+
callback = self.service.listening_topic.subscribe.call_args[1]['callback']
53+
callback(mock_message)
54+
55+
# Assert
56+
self.service.validate.assert_called_once_with(received_message=mock_request_message.data_from())
57+
58+
@patch('src.osw_validator.Validation')
59+
def test_validate_with_valid_file_path(self, mock_validation):
60+
# Arrange
61+
mock_request_message = MagicMock()
62+
mock_request_message.data.jobId = None
63+
mock_request_message.data.file_upload_path = 'test_dataset_url'
64+
65+
# Mock the Validation instance and its return value
66+
mock_validation_instance = mock_validation.return_value
67+
result = ValidationResult()
68+
result.is_valid = True # Simulate successful validation
69+
result.validation_message = ''
70+
mock_validation_instance.validate.return_value = result
71+
72+
self.service.send_status = MagicMock()
73+
74+
# Act
75+
self.service.validate(mock_request_message)
76+
77+
# Assert
78+
self.service.send_status.assert_called_once()
79+
80+
# Extract the actual arguments used in the send_status call
81+
call_args = self.service.send_status.call_args
82+
actual_result = call_args[1]['result']
83+
actual_upload_message = call_args[1]['upload_message']
84+
85+
# Assert that the properties of the result match what we expect
86+
self.assertEqual(actual_result.is_valid, result.is_valid)
87+
self.assertEqual(actual_result.validation_message, result.validation_message)
88+
89+
# Ensure the upload_message is the expected object
90+
self.assertEqual(actual_upload_message, mock_request_message)
91+
92+
@patch('src.osw_validator.ValidationResult')
93+
def test_validate_with_no_file_upload_path(self, mock_validation_result):
94+
# Arrange
95+
mock_request_message = MagicMock()
96+
mock_request_message.data.file_upload_path = None # Simulate None file upload path
97+
98+
# Create the expected failure result
99+
mock_result = mock_validation_result.return_value
100+
mock_result.is_valid = False
101+
mock_result.validation_message = 'Request does not have valid file path specified.'
102+
103+
self.service.send_status = MagicMock()
104+
105+
# Act
106+
self.service.validate(mock_request_message)
107+
108+
# Assert that send_status was called with failure result
109+
self.service.send_status.assert_called_once()
110+
111+
# Extract the actual arguments used in the send_status call
112+
call_args = self.service.send_status.call_args
113+
actual_result = call_args[1]['result']
114+
actual_upload_message = call_args[1]['upload_message']
115+
116+
# Assert that the result indicates failure
117+
self.assertFalse(actual_result.is_valid)
118+
self.assertEqual(actual_result.validation_message, 'Error occurred while validating OSW request Request does not have valid file path specified.')
119+
120+
# Ensure the upload_message is the expected object
121+
self.assertEqual(actual_upload_message, mock_request_message)
122+
123+
@patch('src.osw_validator.Validation')
124+
@patch('src.osw_validator.OSWValidator.has_permission')
125+
def test_validate_with_validation_only_in_message_type(self, mock_has_permission, mock_validation):
126+
"""Test that has_permission is NOT called when 'VALIDATION_ONLY' is in message_type."""
127+
# Arrange
128+
mock_request_message = MagicMock()
129+
mock_request_message.message_id = 'message_id'
130+
131+
# Properly mock the 'data' object to avoid AttributeError
132+
mock_request_message.data = MagicMock()
133+
mock_request_message.data.file_upload_path = 'test_dataset_url'
134+
mock_request_message.message_type = 'VALIDATION_ONLY'
135+
136+
# Ensure has_permission is not called
137+
mock_has_permission.return_value = None
138+
139+
# Mock the Validation instance to simulate a successful validation
140+
mock_validation_instance = mock_validation.return_value
141+
mock_validation_instance.validate.return_value.is_valid = True
142+
mock_validation_instance.validate.return_value.validation_message = 'Validation successful'
143+
144+
# Mock the send_status method
145+
self.service.send_status = MagicMock()
146+
147+
# Act
148+
self.service.validate(mock_request_message)
149+
150+
# Assert
151+
# Ensure has_permission was NOT called since VALIDATION_ONLY is in the message_type
152+
mock_has_permission.assert_not_called()
153+
154+
# Ensure send_status was called with a successful validation result
155+
self.service.send_status.assert_called_once()
156+
157+
# Extract the actual result and upload message
158+
actual_result = self.service.send_status.call_args[1]['result']
159+
actual_upload_message = self.service.send_status.call_args[1]['upload_message']
160+
161+
# Assert the result is valid and the upload_message is the mock_request_message
162+
self.assertTrue(actual_result.is_valid)
163+
self.assertEqual(actual_upload_message, mock_request_message)
164+
165+
166+
167+
if __name__ == '__main__':
168+
unittest.main()

0 commit comments

Comments
 (0)