MCPcopy Index your code
hub / github.com/cabify/timex

github.com/cabify/timex @v1.1.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release v1.1.0 ↗ · + Follow
138 symbols 423 edges 20 files 82 documented · 59%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

timex

Build Status Coverage Status GoDoc

timex is a test-friendly replacement for the time package.

Usage

Just replace your time.Now() by a timex.Now() call, etc.

Mocking

Use timex.Override(...) to replace the current implementation by another one, and use the function it returns to restore the default implementation. You can't override from several tests at the same time. You can use an auto-generated by mockery mock from timexmock package, or a controlled implementation from timextest.

timexmock

There's a timexmock.Mocked(func(mocked *timexmock.Implementation) { ... }) wrapper that automatically creates a mock, sets it as the implementation to be used and defers a tear down to set the default implementation again.

Example:

func TestSleep(t *testing.T) {
    timexmock.Mocked(func(mocked *timexmock.Implementation) {
        mocked.On("Sleep", someDuration).Once()
        defer mocked.AssertExpectations(t)

        timex.Sleep(someDuration)
    })
}

timextest

Timextest provides a more complex API useful to control the behavior of concurrent programs, it is especially useful when the code interacts with timers like time.Ticker. Just like timexmock, timextest also provides a timextest.Mocked(time.Time, func(*TestImplementation)) function to make mocking easier. Few examples can be found in timextest/example_test.go, this is one of them:

func ExampleTestImplementation_NewTicker() {
    timextest.Mocked(now, func(mockedtimex *timextest.TestImplementation) {
        go func() {
            ticker := timex.NewTicker(time.Hour)
            for t := range ticker.C() {
                fmt.Printf("%s\n", t)
            }
        }()

        tickerCall := <-mockedtimex.NewTickerCalls
        tickerCall.Mock.Tick(now.Add(time.Second))
        tickerCall.Mock.Tick(now.Add(2 * time.Second))

        // Output:
        // 2009-11-10 23:00:01 +0000 UTC
        // 2009-11-10 23:00:02 +0000 UTC
    })
}

Drawbacks

Performance

There's an obvious performance impact caused by the indirection of the call, it's actually 20-30% slower, however, in absolute numbers we're talking about 30 nanoseconds per call, so you probably should not worry about that. Notice that the difference is so small that it's not easy to get a stable result.

$ go test -run=NONE -benchmem -benchtime=5s -bench=. .
goos: darwin
goarch: amd64
pkg: github.com/cabify/timex
BenchmarkTimeNow-4      49619665           112 ns/op           0 B/op          0 allocs/op
BenchmarkTimexNow-4     41256012           145 ns/op           0 B/op          0 allocs/op

If you're really worried about performance, you can disable part of the indirection by compiling with timex_disable tag, which will provide results similiar to the native implemenation calls:

$ go test -run=NONE -benchmem -benchtime=5s -bench=. -tags=timex_disable .
goos: darwin
goarch: amd64
pkg: github.com/cabify/timex
BenchmarkTimeNow-4      49866967           116 ns/op           0 B/op          0 allocs/op
BenchmarkTimexNow-4     47965780           109 ns/op           0 B/op          0 allocs/op

Dogma

Oh... yes, we're changing global variables and we'll obviously burn in hell, but if you're really into DI, you can also accept timex.Implementation interface as a dependency, and then inject either timex.Default{} or a testable implementation.

Extension points exported contracts — how you extend this code

Ticker (Interface)
Ticker is an interface similar to what time.Ticker provides, but with C as a function returning the channel instead of a [4 …
ticker.go
Timer (Interface)
Timer is an interface similar to what time.Timer provides, but with C as a function returning the channel instead of acc [4 …
timer.go
Implementation (Interface)
Implementation defines the methods we delegate [3 implementers]
implementation.go

Core symbols most depended-on inside this repo

After
called by 17
implementation.go
Mocked
called by 13
timextest/test_implementation.go
Now
called by 9
implementation.go
Mocked
called by 8
timexmock/mocked.go
After
called by 6
funcs.go
NewTimer
called by 6
funcs.go
Since
called by 6
implementation.go
Now
called by 5
funcs.go

Shape

Function 63
Method 56
Struct 16
Interface 3

Languages

Go100%

Modules by API surface

timextest/test_implementation.go19 symbols
timextest/example_test.go12 symbols
funcs.go11 symbols
timexmock/implementation.go9 symbols
implementation.go9 symbols
default.go9 symbols
timextest/mocked_timer.go8 symbols
funcs_test.go8 symbols
funcs_disabled_test.go8 symbols
funcs_disabled.go8 symbols
default_test.go8 symbols
timextest/mocked_ticker.go6 symbols

For agents

$ claude mcp add timex \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact