Skip to main content

unit-testing

Unit testing best practices and patterns

Informações da origem

Repositório
ffsshhttiikk/opencode-agents-skills
Última atividade na origem
28 de fevereiro de 2026 às 22:55
Idioma detectado do SKILL.md
inglês
Estrelas
3
Forks
2

Opções de instalação

Por padrão, está selecionado o prompt que primeiro revisa a origem. Você pode mudar para um comando direto ou baixar uma cópia local.

Revise os arquivos de origem

Leia o SKILL.md e os arquivos complementares exibidos pelo SkillsMP antes de decidir se vai instalar.

Exibindo SKILL.md

SKILL.md
Instruções da origem · Visualização somente leitura
name
unit-testing
description
Unit testing best practices and patterns
license
MIT
compatibility
opencode
metadata
{"audience":"developers","category":"testing"}
## What I do - Write effective unit tests - Structure test suites - Use test doubles (mocks, stubs, fakes) - Test edge cases and errors - Achieve good coverage - Use parameterized tests - Write readable tests - Follow testing best practices ## When to use me When writing unit tests or improving test coverage. ## Unit Test Structure ```python import pytest from unittest.mock import Mock, patch, MagicMock from dataclasses import dataclass # Arrange-Act-Assert Pattern class TestUserService: """Unit tests for UserService.""" @pytest.fixture def user_repository(self): """Create mock user repository.""" return Mock() @pytest.fixture def email_service(self): """Create mock email service.""" return Mock() @pytest.fixture def service(self, user_repository, email_service): """Create service with dependencies.""" return UserService( user_repository=user_repository, email_service=email_service, ) def test_create_user_saves_and_sends_welcome_email( self, service: UserService, user_repository: Mock, email_service: Mock ): """Test creating a user saves to DB and sends email.""" # Arrange email = "user@example.com" name = "Test User" user_repository.exists_by_email.return_value = False # Act result = service.create_user(email, name) # Assert # Verify repository calls user_repository.exists_by_email.assert_called_once_with(email) user_repository.save.assert_called_once() # Verify email was sent email_service.send_welcome_email.assert_called_once_with( email=email, name=name, ) # Verify result assert result.email == email assert result.name == name assert result.id is not None def test_create_user_raises_error_for_duplicate_email( self, service: UserService, user_repository: Mock ): """Test that duplicate email raises error.""" # Arrange email = "existing@example.com" user_repository.exists_by_email.return_value = True # Act & Assert with pytest.raises(DuplicateEmailError): service.create_user(email, "Test") # Verify save was never called user_repository.save.assert_not_called() ``` ## Using Mocks Effectively ```python from unittest.mock import Mock, patch, MagicMock import pytest class TestPaymentProcessor: """Test payment processor with mocks.""" @patch('app.services.payment_gateway.PaymentGateway') def test_process_payment_success( self, mock_gateway_class ): """Test successful payment processing.""" # Arrange mock_gateway = MagicMock() mock_gateway.process_payment.return_value = { "status": "success", "transaction_id": "tx_123" } mock_gateway_class.return_value = mock_gateway processor = PaymentProcessor(gateway=mock_gateway) # Act result = processor.process( amount=100.00, currency="USD", source="tok_visa" ) # Assert mock_gateway.process_payment.assert_called_once_with( amount=100.00, currency="USD", source="tok_visa", ) assert result.status == "success" assert result.transaction_id == "tx_123" @patch('app.services.payment_gateway.PaymentGateway') def test_process_payment_handles_error( self, mock_gateway_class ): """Test error handling in payment processing.""" # Arrange mock_gateway = MagicMock() mock_gateway.process_payment.side_effect = PaymentError( "Card declined" ) mock_gateway_class.return_value = mock_gateway processor = PaymentProcessor(gateway=mock_gateway) # Act & Assert with pytest.raises(PaymentProcessingError): processor.process( amount=100.00, currency="USD", source="tok_visa" ) ``` ## Parameterized Tests ```python import pytest from hypothesis import given, strategies as st class TestValidator: """Tests for input validator.""" @pytest.mark.parametrize("email,is_valid", [ ("user@example.com", True), ("user.name@example.com", True), ("user+tag@example.com", True), ("invalid", False), ("@example.com", False), ("user@", False), ("user@.com", False), ]) def test_email_validation(self, email: str, is_valid: bool): """Test email validation with various inputs.""" validator = EmailValidator() result = validator.is_valid_email(email) assert result == is_valid @pytest.mark.parametrize("password,expected", [ ("Short1!", False), # Too short ("lowercase1!", False), # No uppercase ("UPPERCASE1!", False), # No lowercase ("NoNumbers!", False), # No numbers ("ValidPass1!", True), ]) def test_password_strength( self, password: str, expected: bool ): """Test password strength validation.""" validator = PasswordValidator() result = validator.is_strong(password) assert result == expected # Property-based testing with Hypothesis class TestMathOperations: """Property-based tests for math operations.""" @given(st.integers(), st.integers()) def test_addition_is_commutative(self, a: int, b: int): """Addition should be commutative: a + b == b + a.""" assert a + b == b + a @given(st.integers(min_value=1)) def test_multiplication_by_one(self, a: int): """Multiplication by one should return same number.""" assert a * 1 == a @given(st.lists(st.integers(), min_size=1)) def test_sum_is_at_least_max(self, numbers: list): """Sum of list should be at least the max value.""" assert sum(numbers) >= max(numbers) @given(st.text(min_size=1)) def test_string_reversal_length(self, s: str): """Reversed string should have same length.""" assert len(s[::-1]) == len(s) ``` ## Testing Edge Cases ```python import pytest from unittest.mock import Mock, patch class TestOrderProcessor: """Test order processor with edge cases.""" def test_empty_cart_raises_error(self): """Test that empty cart raises error.""" repository = Mock() processor = OrderProcessor(repository) with pytest.raises(EmptyCartError): processor.process_order(user_id="123", cart_items=[]) def test_single_item_order(self): """Test order with single item.""" repository = Mock() repository.save.return_value = Mock(id="order_123") processor = OrderProcessor(repository) result = processor.process_order( user_id="123", cart_items=[CartItem(product_id="p1", quantity=1)] ) assert result.id == "order_123" repository.save.assert_called_once() def test_multiple_items_order(self): """Test order with multiple items.""" repository = Mock() repository.save.return_value = Mock(id="order_123") processor = OrderProcessor(repository) items = [ CartItem(product_id="p1", quantity=2), CartItem(product_id="p2", quantity=1), ] result = processor.process_order("123", items) # Verify order was saved assert repository.save.called # Get the order that was saved saved_order = repository.save.call_args[0][0] assert len(saved_order.items) == 2 def test_handles_repository_error(self): """Test error handling when repository fails.""" repository = Mock() repository.save.side_effect = DatabaseConnectionError() processor = OrderProcessor(repository) with pytest.raises(OrderProcessingError): processor.process_order("123", [CartItem("p1", 1)]) def test_calculates_correct_total(self): """Test that order total is calculated correctly.""" repository = Mock() processor = OrderProcessor(repository) items = [ CartItem(product_id="p1", quantity=2, price=10.00), CartItem(product_id="p2", quantity=3, price=15.00), ] order = processor.process_order("123", items) # Total: (2 * 10) + (3 * 15) = 20 + 45 = 65 assert order.total == 65.00 @pytest.mark.parametrize("quantity", [-1, 0]) def test_invalid_quantity_raises_error(self, quantity: int): """Test that invalid quantity raises error.""" repository = Mock() processor = OrderProcessor(repository) with pytest.raises(InvalidQuantityError): processor.process_order( "123", [CartItem("p1", quantity)] ) ``` ## Testing Async Code ```python import pytest import asyncio from unittest.mock import AsyncMock, patch class TestAsyncUserService: """Test async user service.""" @pytest.fixture def mock_repository(self): """Create async mock repository.""" return AsyncMock() @pytest.fixture def mock_cache(self): """Create async mock cache.""" return AsyncMock() @pytest.fixture async def service(self, mock_repository, mock_cache): """Create async service.""" return AsyncUserService( repository=mock_repository, cache=mock_cache, ) @pytest.mark.asyncio async def test_get_user_caches_result( self, service: AsyncUserService, mock_repository: AsyncMock, mock_cache: AsyncMock ): """Test that get_user caches results.""" mock_cache.get.return_value = None mock_repository.find_by_id.return_value = Mock( id="123", name="Test User" ) # Act result = await service.get_user("123") # Assert mock_cache.get.assert_called_once_with("user_123") mock_repository.find_by_id.assert_called_once_with("123") mock_cache.set.assert_called_once() @pytest.mark.asyncio async def test_returns_cached_user( self, service: AsyncUserService, mock_repository: AsyncMock, mock_cache: AsyncMock ): """Test that cached user is returned.""" cached_user = Mock(id="123", name="Cached User") mock_cache.get.return_value = cached_user result = await service.get_user("123") # Should not call repository mock_repository.find_by_id.assert_not_called() assert result == cached_user @pytest.mark.asyncio async def test_handles_not_found(self): """Test handling of user not found.""" mock_repository = AsyncMock() mock_repository.find_by_id.return_value = None mock_cache = AsyncMock() service = AsyncUserService(mock_repository, mock_cache) result = await service.get_user("nonexistent") assert result is None ``` ## Test Fixtures ```python import pytest from typing import Generator from dataclasses import dataclass @dataclass class TestUser: """Test user fixture.""" email: str = "test@example.com" name: str = "Test User" password: str = "SecurePass123!" @pytest.fixture def test_user() -> TestUser: """Create test user.""" return TestUser() @pytest.fixture def new_user(test_user) -> dict: """Create user data dict.""" return { "email": test_user.email, "name": test_user.name, "password": test_user.password, } @pytest.fixture def authenticated_client(client, test_user): """Create authenticated API client.""" token = generate_test_token(test_user.email) client.headers["Authorization"] = f"Bearer {token}" return client @pytest.fixture(scope="session") def database(): """Create test database (session-scoped).""" db = create_test_database() yield db db.close() @pytest.fixture def db_session(database):
Ver no GitHub
Este SKILL.md e muito grande, entao o SkillsMP mostra aqui apenas a primeira secao. Ver no GitHub