🧪 DevLog: Integrated Unit Testing Framework - Test-Driven Development Arrives in JetPascal! #9
jarroddavis68
started this conversation in
DevLog
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Version: JetPascal 0.2.0+
📢 Overview
JetPascal now has built-in unit testing directly integrated into the language! Write tests alongside your code, run them automatically, and get instant feedback - all without external dependencies or frameworks.
This is a game-changer for:
🎯 Why Built-In Unit Testing?
The Problem
Traditional Pascal testing meant:
The Solution
JetPascal makes testing effortless:
That's it.
✅ No external dependencies - Built into the language
✅ No framework installation - Just
UNITTESTMODE ON✅ No separate test projects - Tests live with code
✅ No configuration - It just works
✅ Automatic test discovery - No registration needed
✅ Clean output - Professional test runner included
🔧 Core Features
UNITTESTMODEDirectiveEnable/disable unit testing:
Key behaviors:
ON: Tests are compiled and run via dedicated test runnerOFF: Tests are completely excluded from compilation (zero overhead)JETPASCAL_UNITTESTpreprocessor define for conditional compilationtestBlocksDefine test cases:
Features:
Check()- Boolean AssertionsVerify conditions:
Examples:
Output on failure:
CheckEqual()- Equality with DetailsCompare values with detailed output:
Examples:
Output on failure:
Why CheckEqual vs Check?
Check()only tells you it failedCheckEqual()shows expected vs actual valuesCheckEqual()for better debugging experience💻 Complete Working Example
Basic Program with Tests
Source: ProgramUnitTest.pas
Test Output
Output:
Exit code:
0(success)When Tests Fail
Modified test (intentionally wrong):
Output:
Exit code:
1(failure)Perfect for CI/CD! The exit code tells your build system exactly what happened.
📍 Where Tests Can Live
Programs (Full Test Support)
Behavior:
WriteLnexecutes)main()with test runnerLibraries (Test Support)
Behavior:
Units (Test Support)
Behavior:
🏗️ How It Works Under the Hood
Architecture: Compiler Integration
JetPascal's test framework is deeply integrated into the compiler architecture:
Token-Based Implementation
Each test construct is a SmartToken:
Token architecture benefits:
Generated C++ Code
Pascal test:
Generated C++ (simplified):
Key implementation details:
#ifdeffor zero overhead#linedirectivesConditional Compilation
Normal build (UNITTESTMODE OFF):
Test build (UNITTESTMODE ON):
Result: Binary contains either program OR tests, never both!
🎨 Design Philosophy
DUnit Compatibility
JetPascal's test syntax is inspired by DUnit, Delphi's classic unit testing framework:
DUnit (traditional):
JetPascal:
Why this naming?
Checkclearly indicates testing (not runtime assertions)AssertCheckTrue,CheckFalse,CheckNotEqual, etc.Work Smart, Not Hard
Following JetPascal's philosophy:
std::printlnfor output, not custom formatting#ifdefguards, compile-time test registryTest-Driven Development (TDD)
JetPascal's testing enables proper TDD workflow:
Red → Green → Refactor
💡 Best Practices
DO:
✅ Write descriptive test names -
'Add handles negative numbers'not just'Test 1'✅ Test one thing per test - Focused tests are easier to debug
✅ Use CheckEqual for comparisons - Better error messages than Check
✅ Test edge cases - Zero, negative, empty, null, boundary values
✅ Keep tests simple - Tests should be easier to understand than code
✅ Run tests frequently - After every change, catch regressions early
DON'T:
❌ Don't test implementation details - Test behavior, not internals
❌ Don't make tests depend on each other - Each test must be independent
❌ Don't skip edge case testing - Edge cases find the most bugs
❌ Don't use Check for equality - Use CheckEqual for better diagnostics
❌ Don't write flaky tests - Tests must be deterministic
🎓 Advanced Techniques
Technique 1: Testing Private Functions
Problem: Need to test internal helper functions
Solution: Use conditional compilation
Technique 2: Test Data Setup
Technique 3: Multiple Assertions
Technique 4: Testing Boolean Functions
Technique 5: Complex Expression Testing
🔄 Integration with Build Systems
Exit Codes for CI/CD
Perfect for automated testing:
GitHub Actions Example
Test failure automatically fails the build!
Build System Detection
JetPascal automatically adds test defines to
build.zig:This ensures the C++ compiler sees the correct flags!
📊 Performance Impact
Compilation Time:
Runtime Performance:
Binary Size:
🚦 Current Status & Future Plans
✅ Fully Implemented
UNITTESTMODE ON/OFFdirectivetest 'name' begin...end;blocksCheck(condition)assertionsCheckEqual(expected, actual)assertions🚧 Coming Soon (Phase 2)
CheckTrue(condition)- Explicit true checkCheckFalse(condition)- Explicit false checkCheckNotEqual(exp, act)- Inequality checkCheckGreater(exp, act)- Greater-than checkCheckLess(exp, act)- Less-than checkCheckGreaterOrEqual(exp, act)- ≥ checkCheckLessOrEqual(exp, act)- ≤ checkCheckNull(pointer)- Null pointer checkCheckNotNull(pointer)- Non-null pointer check💡 Future Possibilities
CheckRaises(MyFunc, EMyException)CheckEqual(exp, act, epsilon)CheckContains(haystack, needle)CheckCount(list, 5)🤔 Technical Q&A
Q: How is this different from DUnit?
A: DUnit is an external framework requiring installation. JetPascal's tests are built into the language - no dependencies, no setup, just code.
Q: Can I use both
AssertandCheck?A: Yes, but they behave differently! Pascal's
Assertraises exceptions (stops execution). JetPascal'sChecksets flags (all tests run). UseCheckfor testing.Q: What about FPCUnit or other frameworks?
A: You can still use those! But JetPascal's built-in testing is simpler for most cases and has zero dependencies.
Q: Can I test existing Delphi code?
A: Yes! JetPascal compiles Delphi-compatible Pascal. Add
UNITTESTMODE ONand test blocks - your existing code works as-is.Q: Does this work with cross-compilation?
A: Absolutely! Tests compile and run on any target platform (Windows, Linux, macOS, etc.)
Q: How do I test private/internal functions?
A: In test mode, they're accessible! The
#ifdef JETPASCAL_UNITTESTguards give tests access to everything.Q: Can I test libraries without a main program?
A: Libraries and units register tests but don't generate a runner. You can create a separate test program that uses the library.
Q: What about GUI testing?
A: Current tests are for logic/algorithms. GUI testing frameworks (like VCL testers) would be separate - this tests pure functions.
🎬 Real-World Use Case: Raylib Wrapper Testing
Scenario: Testing a JetPascal raylib wrapper
Benefits:
🎉 Success Stories
Before JetPascal Testing
Developer workflow:
After JetPascal Testing
Developer workflow:
🙏 Acknowledgments
This feature wouldn't exist without:
📝 Closing Thoughts
Built-in unit testing represents a major milestone for JetPascal. It's not just about testing - it's about confidence. Confidence to refactor. Confidence to add features. Confidence that your code works.
The beauty of JetPascal's approach:
Testing is no longer optional. It's effortless.
🚀 Try It Out!
Create test project:
Edit a test file:
Build and test:
Output:
Congratulations! You just wrote your first JetPascal unit test! 🎉
Have questions or cool test examples? Drop them in the comments! We'd love to hear how you're using unit testing in your JetPascal projects.
Happy Testing! 🧪
JetPascal™ - Accelerate Your Code!
Beta Was this translation helpful? Give feedback.
All reactions