Version: 2.0 Date: 2026-03-17 Status: Production-Ready Coverage: 9,400+ tests across 215 test files
This document provides comprehensive guidelines for testing Yole parsers and the broader codebase, covering all 16 test types used in the project.
Key Principle: Targeted, coverage-driven testing achieves the best ROI. All 17 format parsers and 8 network protocol services are thoroughly tested.
| Metric | Value |
|---|---|
| Total test methods | 9,400+ |
| Test files | ~215 |
| Source sets | commonTest, desktopTest, androidUnitTest, wasmJsTest |
| Format parsers tested | 17/17 |
| Protocol services tested | 8/8 |
| Test pass rate | 100% |
Test individual classes and functions in isolation.
Location: shared/src/commonTest/kotlin/digital/vasic/yole/format/[format]/
Pattern: One test class per parser, covering all parsing branches.
Test cross-format interactions and module boundaries.
Location: shared/src/commonTest/kotlin/digital/vasic/yole/format/integration/
Pattern: Test FormatRegistry detection pipeline, format conversion, and parser interop.
Verify behavior under high load and concurrent access.
Location: shared/src/commonTest/kotlin/digital/vasic/yole/format/stress/
Suites: FormatParsingStressTest, ComprehensiveStressTests, ConcurrentFormatParsingStressTest, EdgeCaseStressTest
Pattern: 100+ concurrent coroutines, 10,000+ line documents, sustained high-frequency operations.
Test boundary conditions and unusual inputs.
Location: shared/src/commonTest/kotlin/digital/vasic/yole/format/supremacy/
Pattern: Empty content, whitespace-only, Unicode, mixed encodings, extremely long lines, deeply nested structures.
Test network protocol services with mock HTTP responses.
Location: shared/src/commonTest/kotlin/digital/vasic/yole/network/
Pattern: Mock Ktor HTTP client with predefined responses for each protocol.
Generate random inputs to find edge cases automatically.
Pattern: Random document generation, random format detection, random parse/serialize round-trips.
Verify that all 8 protocol services implement NetworkStorageService consistently.
Location: shared/src/commonTest/kotlin/digital/vasic/yole/network/
Pattern: ContractTestsForProtocols verifies identical behavior across all services for connection, file operations, and error handling.
Test for path traversal, injection, and access control issues.
Pattern: Path traversal with .., normalizePath() validation, OWASP Top 10 patterns, input sanitization for all 17 parsers.
Establish timing baselines and detect regressions.
Location: shared/src/commonTest/kotlin/digital/vasic/yole/format/stress/PerformanceMetricsTests.kt
Baselines: Parse time < 100ms for 10,000 lines, HTML cache hit < 1ms, format detection < 1ms.
Test CircuitBreaker, ConnectionLimiter, and recovery patterns.
Location: shared/src/commonTest/kotlin/digital/vasic/yole/network/
Pattern: Trip circuit breaker, saturate connection limiter, verify recovery after timeout.
Feed semi-random and malformed inputs to parsers.
Pattern: Random byte sequences, truncated documents, mixed format syntax, invalid JSON for Jupyter.
Compare parser output against known-good reference snapshots.
Pattern: Parse a fixed document, compare HTML output against saved snapshot string. Detect unintended changes.
Measure throughput and resource usage under sustained load.
Location: shared/src/commonTest/kotlin/digital/vasic/yole/format/load/
Pattern: Parse hundreds of documents sequentially and concurrently, measure throughput (docs/second).
Test the complete pipeline from raw input to rendered HTML.
Location: shared/src/commonTest/kotlin/digital/vasic/yole/format/e2e/
Pattern: Format detection -> parsing -> HTML generation -> CSS styling, for all 17 formats.
Verify theme contrast ratios and WCAG compliance.
Location: shared/src/commonTest/kotlin/digital/vasic/yole/ui/
Pattern: Theme color contrast ratios, font size accessibility, screen reader compatibility metadata.
Verify suspend functions do not block the calling thread.
Location: shared/src/commonTest/kotlin/digital/vasic/yole/format/nonblocking/
Pattern: Wrap operations in withTimeout() to detect blocking, verify CancellationException propagation.
Use Kover coverage reports to find parsers with low branch coverage:
./gradlew :shared:koverXmlReportLook for parsers with:
- Low branch coverage (<50%)
- High missed branch count (>30)
- Complex conditional logic
- Production usage
Before writing tests, read the parser implementation to understand:
- Branch logic (if/when/try-catch)
- State management (lists, code blocks, tables)
- Format-specific features
- Edge cases
Every parser test suite should include:
- Format-specific feature tests
- Metadata extraction tests (including defaults)
- Validation tests (errors and valid input)
- HTML generation tests (light/dark modes, escaping)
- Edge case tests (empty, whitespace, Unicode)
- Complex document test (all features combined)
All concurrency tests must use KMP-compatible patterns:
@Test
fun concurrentParsingProducesConsistentResults() = runBlocking<Unit> {
val content = "# Test Document\nSome content"
val results = (1..100).map {
async(Dispatchers.Default) {
MarkdownParser().parse(content)
}
}.awaitAll()
// All results must be identical
val reference = results.first().parsedContent
results.forEach { assertEquals(reference, it.parsedContent) }
}- Use
MutexandSemaphorefromkotlinx.coroutines.sync(notjava.util.concurrent) - Use
Clock.System.now()instead ofSystem.currentTimeMillis() - Use
delay()instead ofThread.sleep() - Use
runBlocking<Unit> { }(notrunTest) for JUnit4 compatibility - Test lock ordering: always acquire locks in ascending priority order (see
LOCK_ORDERING.md) - Verify
CancellationExceptionis rethrown in all catch blocks - Test
@Volatilefields under concurrent access - Test
StateFlow.update{}atomic updates
ConcurrencySafetyTest.kt-- Mutex, channel, deadlock preventionRaceConditionDetectionTest.kt-- Check-then-act racesMemoryLeakDetectionTest.kt-- FlowLazyLoader scope cancellationStressAndIntegrationTest.kt-- Rate limiter, lazy loading under 100+ concurrent requests
Performance tests use assertion-based thresholds to detect regressions:
@Test
fun markdownParsingUnder100ms() = runBlocking<Unit> {
val content = generateMarkdownDocument(lines = 10000)
val elapsed = measureTimeMillis {
MarkdownParser().parse(content)
}
assertTrue(elapsed < 100, "Parsing took ${elapsed}ms, expected <100ms")
}| Operation | Threshold | Notes |
|---|---|---|
| Parse 10,000 lines | < 100ms | Any format |
First toHtml() call |
< 50ms | Medium document |
Cached toHtml() call |
< 1ms | Returns cached HTML |
detectByExtension() |
< 1ms | O(1) map lookup |
detectByContent() |
< 5ms | Regex pattern matching |
registerAllParsersLazy() |
< 2ms | Factory lambdas only |
| FormatRegistry lazy init | < 5ms | First access to formats |
| StyleSheets cache hit | < 1ms | CSS from styleSheetCache |
# Desktop only (fast iteration)
./gradlew :shared:desktopTest \
--tests "digital.vasic.yole.format.stress.PerformanceMetricsTests"
# All monitoring metrics
./gradlew :shared:desktopTest \
--tests "digital.vasic.yole.format.stress.MonitoringMetricsTests"/*#######################################################
*
* SPDX-FileCopyrightText: 2026 Milos Vasic
* SPDX-License-Identifier: Apache-2.0
*
* Comprehensive tests for [Parser Name]
*
*########################################################*/
package digital.vasic.yole.format.[formatname]
import digital.vasic.yole.format.TextParser
import kotlin.test.*
class [Parser]ComprehensiveTest {
private lateinit var parser: [Parser]
@BeforeTest
fun setup() {
parser = [Parser]()
}
// ==================== Feature Tests ====================
@Test
fun `should parse [feature] correctly`() {
val content = "[format-specific syntax]"
val doc = parser.parse(content)
assertTrue(doc.parsedContent.contains("[expected]"))
}
// ==================== Metadata Tests ====================
// ==================== Validation Tests ====================
// ==================== HTML Generation Tests ====================
// ==================== Edge Cases ====================
// ==================== Complex Document Tests ====================
}- JUnit4 runner: Tests use
runBlocking<Unit> { }(notrunTest). JUnit4 requiresUnitreturn type;runTestreturnsTestResultwhich causesvoidsignature mismatch. - MockK is JVM-only: Available in
desktopTestandandroidUnitTest, NOT incommonTestorwasmJsTest. - kotlinx-coroutines-test: No WASM variant. Unavailable in
commonTest. - jvmTarget: Must be
"11"in all JVM compilations.
should convert level 1 heading to HTMLshould detect unclosed code blockshould handle source as array instead of stringshould escape HTML special charactersconcurrentParsingShouldNotCorruptResults
- Use backticks for descriptive names
- Start with "should" for behavior tests
- Be specific about what is being tested
- Include the expected behavior
./gradlew test koverHtmlReport
# Report at: shared/build/reports/kover/html/index.html- Parser-specific: 80-90% branch coverage
- Project overall: 63%+ line coverage (current baseline)
- New code: Must not reduce overall coverage
// WRONG - $ will be interpreted
val content = "$x = y$"
// CORRECT - Escape the $
val content = "\$x = y\$"// FRAGILE - Expects exact tag structure
assertTrue(html.contains("<ul><li>Item</li></ul>"))
// ROBUST - Check for key elements
assertTrue(html.contains("<ul>"))
assertTrue(html.contains("<li>Item</li>"))// WRONG - runTest returns TestResult, incompatible with JUnit4
@Test
fun myTest() = runTest { ... }
// CORRECT - runBlocking<Unit> returns Unit
@Test
fun myTest() = runBlocking<Unit> { ... }- 100% test pass rate before committing
- All major features covered (at least one test per feature)
- Edge cases included (empty, unicode, malformed)
- Clear test names (descriptive, follows naming convention)
- No tests may ever be removed, disabled, or skipped
- 80%+ branch coverage for each parser
- 90%+ line coverage for each parser
- Complex document test exercising all features
- Performance considerations (tests run in <1s total)
Document Version: 2.0 Last Updated: 2026-03-17 Maintained By: Engineering Team