feat(quando-vih): implement Clock abstraction for testability
- Add Clock interface with Now() and From(t time.Time) methods - Implement DefaultClock using time.Now() for production code - Implement FixedClock with fixed time for deterministic testing - Add factory functions NewClock() and NewFixedClock(time.Time) - Comprehensive unit tests demonstrating deterministic test patterns - Edge case testing (epoch, year 0001, year 9999, nanoseconds) - Timezone preservation tests - Example tests showing test usage patterns - Performance benchmarks for both clock implementations - 100% test coverage (exceeds 95% requirement) All acceptance criteria met: ✓ Clock interface defined ✓ DefaultClock implementation using time.Now() ✓ FixedClock implementation with fixed time ✓ NewClock() factory function ✓ NewFixedClock(time.Time) factory function ✓ Unit tests demonstrating deterministic test patterns ✓ Godoc comments ✓ Example test showing test usage pattern
This commit is contained in:
parent
6353f28af5
commit
d0cbff9ff8
4 changed files with 350 additions and 2 deletions
79
clock.go
Normal file
79
clock.go
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
package quando
|
||||
|
||||
import "time"
|
||||
|
||||
// Clock provides an abstraction for time operations to enable deterministic testing.
|
||||
// Use DefaultClock in production and FixedClock in tests.
|
||||
//
|
||||
// Example production code:
|
||||
//
|
||||
// clock := quando.NewClock()
|
||||
// date := clock.Now()
|
||||
//
|
||||
// Example test code:
|
||||
//
|
||||
// fixedTime := time.Date(2026, 2, 9, 12, 0, 0, 0, time.UTC)
|
||||
// clock := quando.NewFixedClock(fixedTime)
|
||||
// date := clock.Now() // Always returns Feb 9, 2026
|
||||
type Clock interface {
|
||||
// Now returns the current date according to this clock.
|
||||
Now() Date
|
||||
|
||||
// From converts a time.Time to a Date using this clock's configuration.
|
||||
From(t time.Time) Date
|
||||
}
|
||||
|
||||
// DefaultClock is the standard clock implementation that uses the system time.
|
||||
// It returns the actual current time when Now() is called.
|
||||
type DefaultClock struct{}
|
||||
|
||||
// NewClock returns a new DefaultClock that uses the system time.
|
||||
// This is the clock to use in production code.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// clock := quando.NewClock()
|
||||
// now := clock.Now()
|
||||
func NewClock() Clock {
|
||||
return &DefaultClock{}
|
||||
}
|
||||
|
||||
// Now returns the current date using the system time.
|
||||
func (c *DefaultClock) Now() Date {
|
||||
return Now()
|
||||
}
|
||||
|
||||
// From converts a time.Time to a Date.
|
||||
func (c *DefaultClock) From(t time.Time) Date {
|
||||
return From(t)
|
||||
}
|
||||
|
||||
// FixedClock is a clock implementation that always returns the same time.
|
||||
// This is useful for deterministic testing.
|
||||
type FixedClock struct {
|
||||
fixedTime time.Time
|
||||
}
|
||||
|
||||
// NewFixedClock returns a new FixedClock that always returns the specified time.
|
||||
// This is primarily intended for testing.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// // In tests
|
||||
// fixedTime := time.Date(2026, 2, 9, 12, 0, 0, 0, time.UTC)
|
||||
// clock := quando.NewFixedClock(fixedTime)
|
||||
// date := clock.Now() // Always returns Feb 9, 2026 12:00:00
|
||||
func NewFixedClock(t time.Time) Clock {
|
||||
return &FixedClock{fixedTime: t}
|
||||
}
|
||||
|
||||
// Now returns the fixed time configured for this clock.
|
||||
func (c *FixedClock) Now() Date {
|
||||
return From(c.fixedTime)
|
||||
}
|
||||
|
||||
// From converts a time.Time to a Date.
|
||||
// For FixedClock, this behaves the same as the DefaultClock.
|
||||
func (c *FixedClock) From(t time.Time) Date {
|
||||
return From(t)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue