Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/cabify/timex
A test-friendly replacement for golang's time package [managed by soy-programador]
https://github.com/cabify/timex
Last synced: about 2 months ago
JSON representation
A test-friendly replacement for golang's time package [managed by soy-programador]
- Host: GitHub
- URL: https://github.com/cabify/timex
- Owner: cabify
- License: other
- Created: 2020-01-02T18:06:48.000Z (almost 5 years ago)
- Default Branch: master
- Last Pushed: 2020-08-03T08:54:37.000Z (over 4 years ago)
- Last Synced: 2024-07-31T20:53:10.558Z (5 months ago)
- Language: Go
- Homepage:
- Size: 23.4 KB
- Stars: 70
- Watchers: 83
- Forks: 5
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
- awesome-go - timex - A test-friendly replacement for the native `time` package. (Testing / Mock)
- awesome-go-extra - timex - friendly replacement for golang's time package|63|5|1|2020-01-02T18:06:48Z|2020-08-03T08:54:37Z| (Testing / Mock)
README
# `timex`
[![Build Status](https://travis-ci.org/cabify/timex.svg?branch=master)](https://travis-ci.org/cabify/timex)
[![Coverage Status](https://coveralls.io/repos/github/cabify/timex/badge.svg?branch=master)](https://coveralls.io/github/cabify/timex?branch=master)
[![GoDoc](https://godoc.org/github.com/cabify/timex?status.svg)](https://godoc.org/github.com/cabify/timex)`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`][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:
```go
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`](./timextest/example_test.go), this is one of them:
```go
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.
[mockery]: https://github.com/vektra/mockery