This document outlines the comprehensive TDD improvements made to the Java EMV Reader codebase following the Red-Green-Refactor cycle.
The codebase has been significantly improved using Test-Driven Development principles to ensure:
- Better code quality and reliability
- Comprehensive test coverage for critical EMV components
- Improved maintainability and refactoring safety
- Better error handling and validation
- Red: Write failing tests first to define expected behavior
- Green: Write minimal code to make tests pass
- Refactor: Improve code quality while keeping tests green
Critical for EMV application selection
- ✅ AID creation from hex strings and byte arrays
- ✅ AID length validation (5-16 bytes per ISO 7816-4)
- ✅ RID extraction (first 5 bytes)
- ✅ Partial matching for application selection
- ✅ Proper equals/hashCode implementation
- ✅ Null and invalid input handling
Refactoring done:
- Added input validation with clear error messages
- Added
getRID()method returning RID object - Added
partialMatch()method for EMV application selection
Critical for EMV data structure parsing
- ✅ Simple and complex TLV parsing
- ✅ Nested TLV structure handling
- ✅ Short form and long form length encoding
- ✅ Constructed vs primitive tag detection
- ✅ Multi-byte tag support
- ✅ Child tag searching
- ✅ Error handling for malformed data
- ✅ Serialization/deserialization
Critical for EMV transaction flow
- ✅ Session creation and validation
- ✅ Context initialization (PSE/PPSE discovery)
- ✅ Application selection and state management
- ✅ Processing options initiation
- ✅ Transaction preparation and execution
- ✅ State machine validation
- ✅ Multi-application handling
- ✅ Error scenarios and edge cases
Testing with Mockito:
- Comprehensive mocking of card and terminal interactions
- State transition validation
- Error condition testing
Critical for EMV testing without physical cards
- ✅ Emulator initialization with XML card data
- ✅ APDU command handling (SELECT, READ RECORD, GET DATA, etc.)
- ✅ EMV command sequence testing
- ✅ State maintenance between commands
- ✅ Error handling for invalid commands
- ✅ ATR provision and validation
Refactoring done:
- Improved command validation
- Better error handling (return proper status words instead of exceptions)
- Enhanced input validation
Updated pom.xml with modern testing framework versions:
<!-- Test dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.12.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.21.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>Before TDD:
// Throwing runtime exceptions
throw new RuntimeException("INS " + Util.byte2Hex(ins) + " not implemented");After TDD:
// Proper EMV status word responses
responseBytes = createResponse(null, SW.INSTRUCTION_CODE_NOT_SUPPORTED_OR_INVALID);Before TDD:
// Minimal validation
if (aid == null) {
throw new IllegalArgumentException("Argument 'aid' cannot be null");
}After TDD:
// Comprehensive validation with clear messages
if (aid == null) {
throw new IllegalArgumentException("AID cannot be null");
}
if (aid.length < 5 || aid.length > 16) {
throw new IllegalArgumentException("Invalid AID length: must be 5-16 bytes. Length=" + aid.length);
}Added methods based on TDD requirements:
AID.getRID()- Returns RID object for better type safetyAID.partialMatch()- Essential for EMV application selection- Enhanced CardEmulator command validation
Created TestSuite.java to organize all tests:
@RunWith(Suite.class)
@SuiteClasses({
AIDTest.class,
BERTLVTest.class,
EMVSessionTest.class,
CardEmulatorTest.class,
// ... other tests
})
public class TestSuite {
}# Run all tests
mvn test
# Run specific test class
mvn test -Dtest=AIDTest
# Run test suite
mvn test -Dtest=TestSuite- All critical EMV components now have comprehensive test coverage
- Edge cases and error conditions are properly tested
- Regression prevention through automated testing
- Code changes can be made with confidence
- Refactoring is safer with test safety net
- Clear documentation of expected behavior through tests
- Proper EMV status word responses instead of exceptions
- Better input validation with clear error messages
- Graceful handling of edge cases
- New features can be developed using TDD approach
- Better understanding of code behavior through tests
- Faster debugging with focused test cases
- Certificate Verification - RSA/ECC certificate chain validation
- Cryptographic Operations - SDA, DDA, CDA implementations
- Terminal Risk Management - Floor limits, velocity checking
- PIN Verification - Online/offline PIN processing
- Global Platform - Security domain operations
- Property-Based Testing - Using Hypothesis/QuickCheck patterns
- Integration Testing - Full EMV transaction scenarios
- Performance Testing - Cryptographic operation benchmarks
- Security Testing - Attack vector validation
The TDD improvements have significantly enhanced the Java EMV Reader codebase by:
- Establishing comprehensive test coverage for critical components
- Improving code quality and error handling
- Creating a foundation for future TDD development
- Ensuring EMV specification compliance through automated testing
The codebase is now more reliable, maintainable, and ready for production use in EMV payment processing scenarios.