Skip to content

Writing tests for existing functionality #2

@immerSIR

Description

@immerSIR

Description:
We need to improve our test coverage by adding unit tests for the upload_file_to_blob function in app/services/azure_blob_storage.py. This function is responsible for uploading files to Azure Blob Storage and deleting the local file afterward.

This is an excellent first issue because it involves writing unit tests for cloud storage operations, which is a valuable skill in modern software development. You'll get to work with mocking external services and learn about testing file operations.

Steps to complete:

  1. Locate the upload_file_to_blob function in app/services/azure_blob_storage.py
  2. Create a new test file tests/services/test_azure_blob_storage.py if it doesn't already exist
  3. Write tests that cover the following scenarios:
    • Successful file upload and deletion
    • Handling of non-existent files
    • Proper URL return
    • Error handling for Azure Blob Storage operations
  4. Use mocking to simulate Azure Blob Storage interactions
  5. Run the tests to ensure they all pass
  6. Submit a pull request with your changes

Here's the function you'll be testing:

def upload_file_to_blob(container_name: str, file_path: str) -> str:
    """
    Uploads a file to Azure Blob Storage and returns the URL of the uploaded blob.
    After uploading, the file is deleted from its original location.
    
    :param container_name: The name of the container to upload the file to.
    :param file_path: The path to the file to upload.
    :return: The URL of the uploaded blob.
    """
    # Use the existing filename from the file path
    blob_name = os.path.basename(file_path)
    
    # Create a blob client
    blob_client = blob_service_client.get_blob_client(container=container_name, blob=blob_name)
    
    # Read the file and upload it as a binary stream
    with open(file_path, 'rb') as file_data:
        blob_client.upload_blob(file_data, blob_type="BlockBlob", overwrite=True)
    
    # Delete the file after uploading
    os.remove(file_path)
    
    # Return the URL of the uploaded blob
    return blob_client.url

You can use pytest for writing tests. Here's an example of how you might start:

import pytest
from unittest.mock import patch, mock_open
from app.services.azure_blob_storage import upload_file_to_blob

@pytest.fixture
def mock_blob_service_client():
    with patch('app.services.azure_blob_storage.blob_service_client') as mock_client:
        yield mock_client

def test_upload_file_to_blob_success(mock_blob_service_client, tmp_path):
    # Create a temporary file
    test_file = tmp_path / "test_file.txt"
    test_file.write_text("Test content")
    
    # Mock the blob client
    mock_blob_client = mock_blob_service_client.get_blob_client.return_value
    mock_blob_client.url = "https://test.blob.core.windows.net/container/test_file.txt"
    
    # Call the function
    result = upload_file_to_blob("test-container", str(test_file))
    
    # Assertions
    assert result == "https://test.blob.core.windows.net/container/test_file.txt"
    mock_blob_client.upload_blob.assert_called_once()
    assert not test_file.exists()  # Check if the file was deleted

    # Add more tests here...

Additional Notes:

  • Remember to mock the os.remove function to avoid actually deleting files during tests. You can do this using the patch decorator or context manager from unittest.mock.

    @patch('os.remove')
    def test_upload_file_to_blob_success(mock_remove, mock_blob_service_client, tmp_path):
        # Your test code here
        ...
        mock_remove.assert_called_once_with(str(test_file))
  • Ensure that your test environment has access to all necessary dependencies and that any external services are properly mocked to prevent unintended side effects.

If you need any help or have questions about our testing framework or mocking Azure services, feel free to ask in the comments!

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions