Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added a new test file tests/test_client.py with comprehensive unit tests for RPClient class #237

Open
wants to merge 12 commits into
base: develop
Choose a base branch
from

Conversation

ipetrushchak
Copy link

  • Added a new test file tests/test_client.py with comprehensive unit tests for RPClient class.
    Please assist in resolving the branch creation issue or provide the necessary permissions to proceed.

@HardNorth HardNorth closed this Sep 27, 2024
@HardNorth HardNorth reopened this Oct 9, 2024
Copy link
Member

@HardNorth HardNorth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not LGTM

Comment on lines +7 to +24
@pytest.fixture
def rp_client():
return RPClient(
endpoint="http://example.com",
project="test_project",
api_key="test_api_key",
log_batch_size=20,
is_skipped_an_issue=True,
verify_ssl=True,
retries=3,
max_pool_size=50,
launch_uuid="test_launch_uuid",
http_timeout=(10, 10),
log_batch_payload_size=1024,
mode="DEFAULT",
launch_uuid_print=False,
print_output=OutputType.STDOUT
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fixture looks OK-ish.

Comment on lines +26 to +41
def test_launch_uuid(rp_client):
assert rp_client.launch_uuid == "test_launch_uuid"

def test_endpoint(rp_client):
assert rp_client.endpoint == "http://example.com"

def test_project(rp_client):
assert rp_client.project == "test_project"

def test_step_reporter(rp_client):
assert isinstance(rp_client.step_reporter, StepReporter)

def test_init_session(rp_client):
rp_client._RPClient__init_session()
assert isinstance(rp_client.session, Session)
assert rp_client.session.headers['Authorization'] == 'Bearer test_api_key'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests are OK, but have no much value, since it verifies setting class fields in constructor.

Comment on lines +43 to +165
has_stats=True,
code_ref=None,
retry=False,
test_case_id=None
)
assert result == "item_uuid"
mock_start_test_item.assert_called_once()

def test_finish_test_item(rp_client):
with patch.object(rp_client, 'finish_test_item', return_value="response") as mock_finish_test_item:
result = rp_client.finish_test_item(
item_id="item_uuid",
end_time="2023-01-01T00:00:00.000Z",
status="PASSED",
issue=None,
attributes=[{"key": "value"}],
description="Test Description",
retry=False
)
assert result == "response"
mock_finish_test_item.assert_called_once()

def test_finish_launch(rp_client):
with patch.object(rp_client, 'finish_launch', return_value="response") as mock_finish_launch:
result = rp_client.finish_launch(
end_time="2023-01-01T00:00:00.000Z",
status="PASSED",
attributes=[{"key": "value"}]
)
assert result == "response"
mock_finish_launch.assert_called_once()

def test_update_test_item(rp_client):
with patch.object(rp_client, 'update_test_item', return_value="response") as mock_update_test_item:
result = rp_client.update_test_item(
item_uuid="item_uuid",
attributes=[{"key": "value"}],
description="Updated Description"
)
assert result == "response"
mock_update_test_item.assert_called_once()

def test_get_launch_info(rp_client):
with patch.object(rp_client, 'get_launch_info', return_value={"info": "data"}) as mock_get_launch_info:
result = rp_client.get_launch_info()
assert result == {"info": "data"}
mock_get_launch_info.assert_called_once()

def test_get_item_id_by_uuid(rp_client):
with patch.object(rp_client, 'get_item_id_by_uuid', return_value="item_id") as mock_get_item_id_by_uuid:
result = rp_client.get_item_id_by_uuid("item_uuid")
assert result == "item_id"
mock_get_item_id_by_uuid.assert_called_once()

def test_get_launch_ui_id(rp_client):
with patch.object(rp_client, 'get_launch_ui_id', return_value=123) as mock_get_launch_ui_id:
result = rp_client.get_launch_ui_id()
assert result == 123
mock_get_launch_ui_id.assert_called_once()

def test_get_launch_ui_url(rp_client):
with patch.object(rp_client, 'get_launch_ui_url', return_value="http://example.com/launch") as mock_get_launch_ui_url:
result = rp_client.get_launch_ui_url()
assert result == "http://example.com/launch"
mock_get_launch_ui_url.assert_called_once()

def test_get_project_settings(rp_client):
with patch.object(rp_client, 'get_project_settings', return_value={"settings": "data"}) as mock_get_project_settings:
result = rp_client.get_project_settings()
assert result == {"settings": "data"}
mock_get_project_settings.assert_called_once()

def test_log(rp_client):
with patch.object(rp_client, 'log', return_value=("response",)) as mock_log:
result = rp_client.log(
time="2023-01-01T00:00:00.000Z",
message="Test log message",
level="INFO",
attachment=None,
item_id="item_uuid"
)
assert result == ("response",)
mock_log.assert_called_once()

def test_current_item(rp_client):
with patch.object(rp_client, 'current_item', return_value="item_uuid") as mock_current_item:
result = rp_client.current_item()
assert result == "item_uuid"
mock_current_item.assert_called_once()

def test_clone(rp_client):
with patch.object(rp_client, 'clone', return_value=rp_client) as mock_clone:
result = rp_client.clone()
assert result == rp_client
mock_clone.assert_called_once()

def test_close(rp_client):
with patch.object(rp_client, 'close') as mock_close:
rp_client.close()
mock_close.assert_called_once()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests are pointless at all. It mocks methods and then call this mocked methods, and then verifies that the mock is called. It doesn't even call real code.

Comment on lines +167 to +195
def test_is_skipped_an_issue(rp_client):
assert rp_client.is_skipped_an_issue is True

def test_verify_ssl(rp_client):
assert rp_client.verify_ssl is True

def test_retries(rp_client):
assert rp_client.retries == 3

def test_max_pool_size(rp_client):
assert rp_client.max_pool_size == 50

def test_http_timeout(rp_client):
assert rp_client.http_timeout == (10, 10)

def test_log_batch_payload_size(rp_client):
assert rp_client.log_batch_payload_size == 1024

def test_mode(rp_client):
assert rp_client.mode == "DEFAULT"

def test_launch_uuid_print(rp_client):
assert rp_client.launch_uuid_print is False

def test_print_output(rp_client):
assert rp_client.print_output == OutputType.STDOUT

def test_log_batch_size(rp_client):
assert rp_client.log_batch_size == 20
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests are OK, but have no much value, since it verifies setting class fields in constructor.

Comment on lines +7 to +24
@pytest.fixture
def rp_client():
return RPClient(
endpoint="http://example.com",
project="test_project",
api_key="test_api_key",
log_batch_size=20,
is_skipped_an_issue=True,
verify_ssl=True,
retries=3,
max_pool_size=50,
launch_uuid="test_launch_uuid",
http_timeout=(10, 10),
log_batch_payload_size=1024,
mode="DEFAULT",
launch_uuid_print=False,
print_output=OutputType.STDOUT
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fixture looks OK-ish.

Comment on lines +26 to +41
def test_launch_uuid(rp_client):
assert rp_client.launch_uuid == "test_launch_uuid"

def test_endpoint(rp_client):
assert rp_client.endpoint == "http://example.com"

def test_project(rp_client):
assert rp_client.project == "test_project"

def test_step_reporter(rp_client):
assert isinstance(rp_client.step_reporter, StepReporter)

def test_init_session(rp_client):
rp_client._RPClient__init_session()
assert isinstance(rp_client.session, Session)
assert rp_client.session.headers['Authorization'] == 'Bearer test_api_key'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests are OK, but have no much value, since it verifies setting class fields in constructor.

Comment on lines +43 to +165
has_stats=True,
code_ref=None,
retry=False,
test_case_id=None
)
assert result == "item_uuid"
mock_start_test_item.assert_called_once()

def test_finish_test_item(rp_client):
with patch.object(rp_client, 'finish_test_item', return_value="response") as mock_finish_test_item:
result = rp_client.finish_test_item(
item_id="item_uuid",
end_time="2023-01-01T00:00:00.000Z",
status="PASSED",
issue=None,
attributes=[{"key": "value"}],
description="Test Description",
retry=False
)
assert result == "response"
mock_finish_test_item.assert_called_once()

def test_finish_launch(rp_client):
with patch.object(rp_client, 'finish_launch', return_value="response") as mock_finish_launch:
result = rp_client.finish_launch(
end_time="2023-01-01T00:00:00.000Z",
status="PASSED",
attributes=[{"key": "value"}]
)
assert result == "response"
mock_finish_launch.assert_called_once()

def test_update_test_item(rp_client):
with patch.object(rp_client, 'update_test_item', return_value="response") as mock_update_test_item:
result = rp_client.update_test_item(
item_uuid="item_uuid",
attributes=[{"key": "value"}],
description="Updated Description"
)
assert result == "response"
mock_update_test_item.assert_called_once()

def test_get_launch_info(rp_client):
with patch.object(rp_client, 'get_launch_info', return_value={"info": "data"}) as mock_get_launch_info:
result = rp_client.get_launch_info()
assert result == {"info": "data"}
mock_get_launch_info.assert_called_once()

def test_get_item_id_by_uuid(rp_client):
with patch.object(rp_client, 'get_item_id_by_uuid', return_value="item_id") as mock_get_item_id_by_uuid:
result = rp_client.get_item_id_by_uuid("item_uuid")
assert result == "item_id"
mock_get_item_id_by_uuid.assert_called_once()

def test_get_launch_ui_id(rp_client):
with patch.object(rp_client, 'get_launch_ui_id', return_value=123) as mock_get_launch_ui_id:
result = rp_client.get_launch_ui_id()
assert result == 123
mock_get_launch_ui_id.assert_called_once()

def test_get_launch_ui_url(rp_client):
with patch.object(rp_client, 'get_launch_ui_url', return_value="http://example.com/launch") as mock_get_launch_ui_url:
result = rp_client.get_launch_ui_url()
assert result == "http://example.com/launch"
mock_get_launch_ui_url.assert_called_once()

def test_get_project_settings(rp_client):
with patch.object(rp_client, 'get_project_settings', return_value={"settings": "data"}) as mock_get_project_settings:
result = rp_client.get_project_settings()
assert result == {"settings": "data"}
mock_get_project_settings.assert_called_once()

def test_log(rp_client):
with patch.object(rp_client, 'log', return_value=("response",)) as mock_log:
result = rp_client.log(
time="2023-01-01T00:00:00.000Z",
message="Test log message",
level="INFO",
attachment=None,
item_id="item_uuid"
)
assert result == ("response",)
mock_log.assert_called_once()

def test_current_item(rp_client):
with patch.object(rp_client, 'current_item', return_value="item_uuid") as mock_current_item:
result = rp_client.current_item()
assert result == "item_uuid"
mock_current_item.assert_called_once()

def test_clone(rp_client):
with patch.object(rp_client, 'clone', return_value=rp_client) as mock_clone:
result = rp_client.clone()
assert result == rp_client
mock_clone.assert_called_once()

def test_close(rp_client):
with patch.object(rp_client, 'close') as mock_close:
rp_client.close()
mock_close.assert_called_once()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests are pointless at all. It mocks methods and then call this mocked methods, and then verifies that the mock is called. It doesn't even call real code.

Comment on lines +167 to +195
def test_is_skipped_an_issue(rp_client):
assert rp_client.is_skipped_an_issue is True

def test_verify_ssl(rp_client):
assert rp_client.verify_ssl is True

def test_retries(rp_client):
assert rp_client.retries == 3

def test_max_pool_size(rp_client):
assert rp_client.max_pool_size == 50

def test_http_timeout(rp_client):
assert rp_client.http_timeout == (10, 10)

def test_log_batch_payload_size(rp_client):
assert rp_client.log_batch_payload_size == 1024

def test_mode(rp_client):
assert rp_client.mode == "DEFAULT"

def test_launch_uuid_print(rp_client):
assert rp_client.launch_uuid_print is False

def test_print_output(rp_client):
assert rp_client.print_output == OutputType.STDOUT

def test_log_batch_size(rp_client):
assert rp_client.log_batch_size == 20
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests are OK, but have no much value, since it verifies setting class fields in constructor.

Comment on lines +197 to +242
def test_get_item_id_by_uuid_not_found(rp_client):
with patch.object(rp_client, 'get_item_id_by_uuid', return_value=None) as mock_get_item_id_by_uuid:
result = rp_client.get_item_id_by_uuid("non_existent_uuid")
assert result is None
mock_get_item_id_by_uuid.assert_called_once()

def test_start_launch_with_rerun(rp_client):
with patch.object(rp_client, 'start_launch', return_value="launch_uuid") as mock_start_launch:
result = rp_client.start_launch(
name="Test Launch",
start_time="2023-01-01T00:00:00.000Z",
description="Test Description",
attributes=[{"key": "value"}],
rerun=True,
rerun_of="previous_launch_uuid"
)
assert result == "launch_uuid"
mock_start_launch.assert_called_once()

def test_finish_test_item_with_issue(rp_client):
issue = Issue(issue_type="BUG", comment="Test issue")
with patch.object(rp_client, 'finish_test_item', return_value="response") as mock_finish_test_item:
result = rp_client.finish_test_item(
item_id="item_uuid",
end_time="2023-01-01T00:00:00.000Z",
status="FAILED",
issue=issue,
attributes=[{"key": "value"}],
description="Test Description",
retry=False
)
assert result == "response"
mock_finish_test_item.assert_called_once()

def test_log_with_attachment(rp_client):
attachment = {"name": "screenshot.png", "data": b"binary_data", "mime": "image/png"}
with patch.object(rp_client, 'log', return_value=("response",)) as mock_log:
result = rp_client.log(
time="2023-01-01T00:00:00.000Z",
message="Test log message with attachment",
level="INFO",
attachment=attachment,
item_id="item_uuid"
)
assert result == ("response",)
mock_log.assert_called_once()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests are pointless at all. It mocks methods and then call this mocked methods, and then verifies that the mock is called. It doesn't even call real code.

Copy link

@oleksiidonchakkf oleksiidonchakkf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did a quick glance over the code, feel free to ignore :)

)

def test_launch_uuid(rp_client):
assert rp_client.launch_uuid == "test_launch_uuid"
Copy link

@oleksiidonchakkf oleksiidonchakkf Oct 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rather make a single test with no fixtures:

def test_constructor():
  rp_client = ...
  assert rp_client.field1 == "..."
  assert rp_client.field2 == "..."

assert isinstance(rp_client.step_reporter, StepReporter)

def test_init_session(rp_client):
rp_client._RPClient__init_session()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is calling a private method. Sign of something wrong with design


def test_get_launch_info(rp_client):
with patch.object(rp_client, 'get_launch_info', return_value={"info": "data"}) as mock_get_launch_info:
result = rp_client.get_launch_info()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests like these don't make much sense because they are doing the following:

  1. Create an object
  2. Mock its function to return a value
  3. Call the function
  4. Assert it has been called and returned the value (Sure thing! What would it return otherwise?)

assert result == "item_id"
mock_get_item_id_by_uuid.assert_called_once()

def test_get_launch_ui_id(rp_client):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for this file. The only meaningful test is the one testing the constructor

By the way, the idea of creating an object via a fixture is ok for the tests if you need a fresh object per test. So, the code is correct

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants