20260504 - Super fast tests covering 100% of your code
AL test design patterns for fast tests with 100% coverage of the tested objects, shown on a payment provider integration. It uses interfaces, enums, stubs and spies, and passes records as parameters to avoid database calls and external API calls. The presenter reports over 200 tests running in milliseconds.
- Introduction and housekeeping
- About the presenter and the topic
- Inspiration from Vjeko and coding patterns
- Scenario and requirements for payment integration
- Demo of the payment application
- Test results and code coverage demonstration
- Environment concept and testing scenarios
- Context interfaces and enum-based implementations
- Environment interfaces and design patterns
- Reducing paths and code organization strategy
- Implementation of app environment interface
- Testing with stub and spy patterns
- Achieving 100% code coverage with interfaces
- Testing API calls without external dependencies
- Simulating API responses with global variables
- Fast testing through parameter passing and email handling
- Code hierarchy and minimizing database calls
- AI development and design considerations
- Decoupling side effects with event publishers
- Pure functions and dependency injection design
- API operation patterns and interface design
- Addressing limitations and robustness
- Closing remarks and next steps
Overview
The webinar walks through a payment integration app and shows how it reaches 100% code coverage of the objects under test, except event subscribers. The app switches to test mode outside production. The presenter builds this with context interfaces, environment interfaces, and enums in place of booleans, so that each code path can be tested with stub or spy implementations.
It then covers testing API logic without external calls, passing records as parameters so tests use temporary records, and reducing database gets to one. It also covers AI assistance for writing tests, pure functions, event publishers for side effects, the risk of too many parameters, and an API operation record pattern.
Key points
- Environment interfaces abstract the platform (sandbox or production), current company and evaluation company status, so tests can cover each environment path with stubs.
- A stub returns fixed data without tracking usage; a spy also records which functions were called so tests can check them later.
- API logic is tested by implementing an interface that simulates HTTP responses, so no external calls are made. The real HTTP client implementation is not tested this way.
- Passing records by reference as parameters lets tests use temporary records and skip database inserts and gets. It requires changing function signatures. Passing setup down from the top reduced three gets to one.
- Coverage is 100% only for the objects being tested and excludes event subscribers.
- Moving setup retrieval into parameters is dependency injection and can lead to too many parameters. The presenter suggests rethinking the design or introducing interfaces.
- An API operation record holds the endpoint, method, payload and response so one function can handle any API call. This moves complexity into the record structure.
Features
| Feature | Status | At |
|---|---|---|
| 100% code coverage testing pattern | status not stated, demoed | 4:47 |
| Payment API integration with environment-aware mode switching | status not stated, demoed | 7:13 |
| Fast automated testing framework | status not stated, demoed | 11:49 |
| GitHub AL-Go integration with test reporting | status not stated, demoed | 13:00 |
| Context interfaces pattern | status not stated, demoed | 16:05 |
| Environment interfaces | status not stated, demoed | 18:29 |
| Enum-based state management | status not stated, demoed | 20:25 |
| Test doubles with stubs and spies | status not stated, demoed | 26:15 |
| Environment stub implementation for testing | status not stated, demoed | 27:18 |
| API testing without external calls | status not stated, demoed | 31:36 |
| API spy variables for tracking calls | status not stated, demoed | 34:30 |
| Record parameter passing for fast testing | status not stated, demoed | 39:07 |
| Application state management for test scenarios | status not stated, demoed | 40:43 |
| Single database get optimization | status not stated, demoed | 43:33 |
| AI assistance for code generation and testing | status not stated, demoed | 45:40 |
| Event publishers for separating concerns | status not stated, demoed | 49:14 |
| Pure functions for testability | status not stated, demoed | 50:37 |
| Dependency injection parameter hell trade-off | status not stated | 52:48 |
| Modular app architecture | status not stated, demoed | 54:06 |
| API operation record pattern | status not stated, demoed | 54:57 |
| Interface pattern for consistent signatures | status not stated, demoed | 55:46 |
AL objects mentioned
As heard in the captions. A name that matches one object page by exact type and name links to it; the others stay as named.
- other “navigate BC” at 4:21
- interface “number series single” at 16:48
- enum “system environment” at 21:59
- interface “I environment” at 22:35
- codeunit “app environment” at 22:35
- interface “API request” at 18:40
- interface “send function” at 32:11
- codeunit “stop production environment code unit” at 29:17
- interface “API interface” at 31:58
- codeunit “payment request task” at 43:50
- interface “environment interface” at 58:27
Not found in BC28-30: interface “number series single”, enum “system environment”, interface “I environment”, codeunit “app environment”, interface “API request”, interface “send function”, codeunit “stop production environment code unit”, interface “API interface”, codeunit “payment request task”, interface “environment interface”.
Quotes
- 5:04 “and he gave some examples and he he told his audience that he had 100 code coverage”
- 6:50 “100% code coverage is really different from from 99%”
- 8:29 “we can only be in production mode when we’re running in a production environment. So, basically, if we make a copy of the data”
- 11:49 “you can see that they’re all running in milliseconds. I can run the tests. I run them all. There’s uh a bit over 200”
- 12:27 “I have 100% code coverage on everything except for some event subscribers, which which is rather irrelevant, but I every path is covered by”
Presenters (as heard): Fred, Finn Pedersen, Vieco, Luke, Hilmar Espen, Hilmar.
