tawada / grass-grower

0 stars 0 forks source link

Add unit tests for `routers/routers_utils.py` and `routers/code_generator.py` modules to improve code reliability and prevent regression bugs. #115

Open tawada opened 3 months ago

tawada commented 3 months ago

While the code is comprehensive and well-structured, one notable issue is the absence of unit tests for the routers/routers_utils.py and routers/code_generator.py modules. Unit tests are crucial for ensuring that each part of the application behaves as expected, especially in dynamic and complex functionalities like those found in the code_generator and send_messages_to_system functions. In the absence of these tests, changes to the code in these modules can introduce unintended bugs that might go unnoticed until a later stage, potentially causing larger issues in the overall application. Here's why this is an issue and some proposed tests to mitigate it:

Why This is an Issue

  1. Code Reliability: Without unit tests, it's difficult to guarantee the reliability of functions, especially ones involving external interactions like API calls or system commands.
  2. Regression Bugs: Future changes or refactoring might introduce bugs, and without tests, these issues might be harder to detect.
  3. Confidence in Changes: Developers might hesitate to make necessary changes or optimizations due to the fear of breaking existing functionalities.

Proposed Unit Test Ideas

For routers/routers_utils.py

  1. Test send_messages_to_system function:
    • Ensure that the function correctly appends the system instruction to the messages and calls the generate_text method of the services.llm module.
import pytest
from unittest.mock import patch
from routers.routers_utils import send_messages_to_system

def test_send_messages_to_system():
    messages = [{"role": "user", "content": "Test message"}]
    system_instruction = "Test Instruction"

    with patch('services.llm.get_openai_client') as mock_get_client, \
         patch('services.llm.generate_text') as mock_generate_text:

        mock_client = mock_get_client.return_value
        mock_generate_text.return_value = "Generated Text"

        result = send_messages_to_system(messages, system_instruction)

        expected_messages = [{"role": "user", "content": "Test message"},
                             {"role": "system", "content": "Test Instruction"}]

        mock_generate_text.assert_called_once_with(expected_messages, mock_client)
        assert result == "Generated Text"

For routers/code_generator.py

  1. Test the generate_code_from_issue function:
    • Mock dependencies like services.github and ensure the function correctly fetches the issue and generates code using the LLM service.
import pytest
from unittest.mock import patch, MagicMock
from routers.code_generator import generate_code_from_issue

def test_generate_code_from_issue():
    issue_id = 1
    repo = "test_repo"
    branch = "main"
    code_lang = "python"

    mock_issue = MagicMock()
    mock_issue.id = issue_id

    with patch('services.github.setup_repository') as mock_setup_repo, \
         patch('services.github.get_issue_by_id', return_value=mock_issue) as mock_get_issue, \
         patch('routers.routers_utils.send_messages_to_system', return_value="Generated Code") as mock_send_messages:

        generated_code = generate_code_from_issue(issue_id, repo, branch, code_lang)

        mock_setup_repo.assert_called_once_with(repo, branch)
        mock_get_issue.assert_called_once_with(repo, issue_id)
        assert mock_send_messages.called
        assert generated_code == "Generated Code"
  1. Test the generate_readme function:
    • Ensure that generate_readme correctly handles the generation of the README file, branching operations, and committing/pushing the changes.
import pytest
from unittest.mock import patch, MagicMock
from routers.code_generator import generate_readme

def test_generate_readme():
    repo = "test_repo"
    branch = "main"
    code_lang = "python"

    with patch('services.github.setup_repository') as mock_setup_repo, \
         patch('logic.logic_utils.get_file_content', return_value="Current README") as mock_get_content, \
         patch('routers.routers_utils.send_messages_to_system', return_value="Generated README") as mock_send_messages, \
         patch('services.github.checkout_new_branch') as mock_checkout_new_branch, \
         patch('logic.logic_utils.write_to_file') as mock_write_to_file, \
         patch('services.github.commit') as mock_commit, \
         patch('services.github.push_repository') as mock_push_repo, \
         patch('services.github.checkout_branch') as mock_checkout_branch:

        result = generate_readme(repo, branch, code_lang)

        mock_setup_repo.assert_called_once_with(repo, branch)
        mock_get_content.assert_called_once()
        mock_send_messages.assert_called()
        mock_checkout_new_branch.assert_called_once_with(repo, "update-readme")
        mock_write_to_file.assert_called_once()
        mock_commit.assert_called_once_with(repo, "Update README.md")
        mock_push_repo.assert_called_once_with(repo, "update-readme")
        mock_checkout_branch.assert_called_once_with(repo, "main")
        assert result == True

::: Note: Tests should be isolated and should only test a single unit of functionality, avoiding side effects or dependencies on external systems or network calls.

Conclusion

Adding these unit tests will ensure that the key functionalities in your application are reliable, easier to maintain, and resilient against future changes or refactoring. It would also give developers greater confidence in making necessary improvements to the codebase.