slogan3

Help me bij het implementeren van best practices voor het schrijven van onderhoudbare unittests

description

Door deze best practices te volgen, maak je unittests die niet alleen effectief zijn, maar ook gemakkelijker te beheren over de tijd, waardoor technische schuld wordt verminderd en de codekwaliteit verbetert.

prompt

try_prompt

Ik wil ervoor zorgen dat mijn unittests onderhoudbaar zijn en de beste praktijken volgen. Geef me een uitgebreide gids over hoe ik duidelijke, beknopte en effectieve unittests voor mijn projec ... more
generate_helper
disclaimerOnPageApi image_legal_disclaimer...

ai_answers

provider: openai
model: gpt-4.1-nano
Zeker! Hier is een uitgebreide gids voor het schrijven van onderhoudbare, duidelijke en effectieve unittests voor je Python-webapplicatie, inclusief naamgevingsconventies, codeorganisatie en documentatiepraktijken: ### 1. Algemene principes voor goede unittests - **Isolatie:** Test één stuk functionaliteit per test. Mock externe afhankelijkheden. - **Repliceerbare tests:** Zorg dat tests altijd hetzelfde resultaat geven, onafhankelijk van omgeving of tijd. - **Snelle uitvoering:** Tests moeten snel zijn om frequent gebruik te stimuleren. - **Zelfvoorzienend:** Tests moeten zelfstandig kunnen draaien zonder afhankelijkheden van externe systemen. ### 2. Naamgevingsconventies - **Testclass-namen:** Gebruik de naam van de klasse of functie gevolgd door `Test`. Bijvoorbeeld: `TestLoginFunctionality`. - **Testmethoden:** Beschrijf wat de test doet, bijvoorbeeld: - `test_successful_login` - `test_invalid_password` - `test_missing_fields` - **Gebruik duidelijke, beschrijvende namen** zonder afkortingen, zodat bij het lezen van de testdirect zichtbaar is wat er wordt getest. ### 3. Structuur en organisatie van testcode - **Mapstructuur:** Plaats je tests in een aparte map, bijvoorbeeld `tests/`. - **Bestandstructuur:** Maak aparte testbestanden voor verschillende modules, bijvoorbeeld `test_auth.py`, `test_views.py`. - **Setup en teardown:** Gebruik `setUp()` en `tearDown()` methoden voor herbruikbare setup-code. Overweeg `setUpClass()` en `tearDownClass()` voor klasse-brede setup. - **Gebruik van fixtures:** Gebruik fixtures of factory-bibliotheken (zoals `pytest fixtures` of `factory_boy`) voor het genereren van testdata. ### 4. Testmethoden schrijven - **Arrange-Act-Assert:** Volg deze structuur: - **Arrange:** Bereid je data en omgeving voor. - **Act:** Voer de actie uit, bijvoorbeeld een functie-aanroep. - **Assert:** Controleer of het resultaat klopt. - **Minimaliseer complexiteit:** Houd tests kort en duidelijk, één ding per test. - **Test verschillende scenario’s:** Positieve en negatieve paden, randgevallen. ### 5. Gebruik van mocking en patching - **Mock externe systemen:** Bijvoorbeeld databases, API's, bestandsystemen. - **Gebruik `unittest.mock`:** Bijvoorbeeld `patch()` om functies of klassen te mocken. - **Vermijd echte externe verbindingen** in unittests, focus op de logica. ### 6. Beveilig je tests tegen flakiness - **Deterministische tests:** Vermijd tijdsafhankelijke tests. - **Geen afhankelijkheid van netwerk of externe systemen.** ### 7. Documentatie en commentaar - **Duidelijke naamgeving:** Zoals eerder genoemd. - **In-code commentaar:** Leg uit waarom een test bestaat, niet wat de code doet. - **Gebruik docstrings:** Voeg korte beschrijvingen toe aan testklassen en -methoden: ```python class TestLoginFunctionality(unittest.TestCase): """Testen van het inlogproces van de webapplicatie.""" def test_successful_login(self): """Verifieer dat een geldige login succesvol is.""" ... ``` - **Testdocumentatie:** Overweeg een overzicht of README te maken met testdoelen. ### 8. Integratie met CI/CD - **Automatiseer tests:** Integreer met CI/CD pipelines zoals GitHub Actions, GitLab CI, Jenkins. - **Run alle tests bij elke commit:** Zo voorkom je regressies. ### 9. Gebruik van testframeworks en hulpmiddelen - **Unittest:** Python’s ingebouwde framework. - **Pytest:** Meer flexibiliteit en eenvoud. - **Factory_boy, Faker:** Voor testdata. - **Coverage.py:** Om testdekking te meten. ### 10. Voorbeeldstructuur ```plaintext project/ │ ├── app/ │ ├── __init__.py │ ├── views.py │ ├── models.py │ └── ... │ ├── tests/ │ ├── __init__.py │ ├── test_views.py │ ├── test_models.py │ └── test_auth.py │ └── README.md ``` --- ### Samenvatting - Gebruik duidelijke, beschrijvende namen voor testklassen en methoden. - Organiseer tests logisch en herbruikbaar. - Schrijf korte, gerichte tests volgens Arrange-Act-Assert. - Gebruik mocking om afhankelijkheden te isoleren. - Documenteer je tests met commentaar en docstrings. - Automatiseer en integreer tests in je ontwikkelproces. Door deze richtlijnen te volgen, zorg je voor een onderhoudbare en effectieve testsuite die je ontwikkelproces ondersteunt en de kwaliteit van je webapplicatie waarborgt.
provider: deepseek
model: deepseek-chat
### Uitgebreide Gids voor Onderhoudbare Unittests in Python Webapplicaties #### 1. Basisprincipes van Effectieve Unittests **FIRST-principes:** - **Fast**: Tests moeten snel uitvoerbaar zijn (milliseconden per test) - **Isolated**: Elke test moet onafhankelijk werken - **Repeatable**: Resultaten moeten consistent zijn - **Self-validating**: Tests slagen of falen automatisch - **Timely**: Schrijf tests vóór of tijdens ontwikkeling #### 2. Naamgevingsconventies **Testklassen:** ```python class TestUserService: class TestAuthenticationMiddleware: class TestPaymentValidation: ``` **Testmethoden:** ```python def test_returns_user_when_valid_credentials(self): def test_raises_authentication_error_when_invalid_token(self): def test_creates_order_with_correct_total_amount(self): ``` **Bestandsnamen:** ``` test_services.py test_models.py test_authentication.py test_api_endpoints.py ``` #### 3. Teststructuur (AAA-patroon) ```python def test_user_registration_success(self): # Arrange user_data = { 'email': 'test@example.com', 'password': 'securepassword123' } user_service = UserService() # Act result = user_service.register_user(user_data) # Assert assert result.id is not None assert result.email == user_data['email'] ``` #### 4. Testorganisatie **Mappenstructuur:** ``` project/ ├── src/ │ ├── services/ │ ├── models/ │ └── api/ └── tests/ ├── unit/ │ ├── services/ │ ├── models/ │ └── api/ ├── integration/ └── conftest.py ``` **Fixture-organisatie:** ```python # conftest.py import pytest from src.models import User @pytest.fixture def sample_user(): return User( email='test@example.com', username='testuser' ) @pytest.fixture def authenticated_client(): client = TestClient(app) client.login(test_user) return client ``` #### 5. Webapplicatie-specifieke Teststrategie **API endpoint tests:** ```python class TestUserAPI: def test_get_user_returns_200(self, authenticated_client): response = authenticated_client.get('/api/users/1') assert response.status_code == 200 def test_create_user_requires_authentication(self, client): response = client.post('/api/users', json={...}) assert response.status_code == 401 ``` **Database tests:** ```python @pytest.mark.django_db # Voor Django class TestUserModel: def test_user_creation(self): user = User.objects.create( username='testuser', email='test@example.com' ) assert user.pk is not None ``` #### 6. Mocking en Testdoubles ```python from unittest.mock import Mock, patch class TestPaymentService: @patch('services.payment_gateway.charge') def test_process_payment_calls_gateway(self, mock_charge): payment_service = PaymentService() payment_service.process_payment(amount=100, token='tok_123') mock_charge.assert_called_once_with(100, 'tok_123') ``` #### 7. Testdocumentatie **Docstrings in tests:** ```python def test_password_hashing(): """ Test dat wachtwoorden correct worden gehashed. Scenario: - Gebruiker creëert account met wachtwoord - Wachtwoord moet worden gehashed voordat het wordt opgeslagen - Origineel wachtwoord mag niet in database staan """ # Test implementatie ``` **Testcategorieën:** ```python @pytest.mark.slow class TestPerformance: def test_large_data_processing(self): # Langzame performance test pass @pytest.mark.security class TestAuthentication: def test_brute_force_protection(self): # Security-gerelateerde test pass ``` #### 8. Onderhoudbare Testpraktijken **Test Data Factory:** ```python # tests/factories.py class UserFactory: @staticmethod def create_user(**kwargs): defaults = { 'username': 'testuser', 'email': 'test@example.com', 'is_active': True } defaults.update(kwargs) return User(**defaults) ``` **Herbruikbare Assertions:** ```python # tests/assertions.py def assert_valid_user_response(response): assert response.status_code == 200 assert 'id' in response.json() assert 'email' in response.json() assert 'username' in response.json() ``` #### 9. Testconfiguratie **pytest.ini:** ```ini [tool:pytest] testpaths = tests/unit python_files = test_*.py python_classes = Test* python_functions = test_* addopts = --verbose --strict-markers markers = slow: langzame tests integration: integratietests security: security tests ``` #### 10. Continue Integratie **GitHub Actions voorbeeld:** ```yaml name: Tests on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Run tests run: | pytest --cov=src --cov-report=xml ``` #### 11. Veelgemaakte Fouten om te Vermijden - **Te veel asserts per test** → Eén duidelijke verantwoordelijkheid - **Testinterdependentie** → Elke test moet isolaat werken - **Magic numbers** → Gebruik beschrijvende constanten - **Over-mocking** → Mock alleen externe afhankelijkheden - **Testen van implementatiedetails** → Test gedrag, niet implementatie #### 12. Tools en Libraries - **pytest**: Primaire testframework - **factory_boy**: Test data factories - **freezegun**: Voor tijd-gerelateerde tests - **responses**: Voor mocking HTTP requests - **pytest-django**: Django-specifieke testhelpers Deze aanpak zorgt voor schaalbare, onderhoudbare tests die meegroeien met je webapplicatie en consistent betrouwbare resultaten geven.