Skip to content

Better alternative to Eventually() #902

@maratori

Description

@maratori

I've found that Eventually is not really useful:

  1. I can't use assertions inside condition.
  2. Error message doesn't help to understand failure cause: Condition never satisfied.

So I use func WaitFor instead: gist.

The only disadvantage compared to Eventually:

  • WaitFor will not stop after timeout (immediately). It will call function one more time to pass error message from assertions inside that function to the test.
// WaitFor calls fn (once in tick) until it passes or timeout expired.
//
// Attempt is failed if any of following methods called in fn:
//  - Fail/FailNow
//  - Error/Errorf
//  - Fatal/Fatalf
// Otherwise attempt is considered as successful and WaitFor stops.
//
// WaitFor receives test object as the first argument.
// It is passed to fn only on the last attempt. All other attempts use fakeT.
// So the test will fail only after timeout expired.
//
// Note: t.Log() and other methods will print to stdout only on the last attempt.
func WaitFor(t TestingT, timeout time.Duration, tick time.Duration, fn func(t TestingT)) {
	timer := time.NewTimer(timeout)
	ticker := time.NewTicker(tick)
	defer timer.Stop()
	defer ticker.Stop()
	for {
		ft := &fakeT{name: t.Name()}
		didPanic := false
		func() {
			defer func() {
				if recover() != nil {
					didPanic = true
				}
			}()
			fn(ft)
		}()
		if !ft.Failed() && !didPanic {
			return
		}

		select {
		case <-timer.C:
			fn(t)
			return
		case <-ticker.C:
		}
	}
}

The rest code (with examples) can be found in this gist.

It would be great to see the same feature in testify.

Metadata

Metadata

Assignees

No one assigned

    Labels

    assert.EventuallyAbout assert.Eventually/EventuallyWithTenhancementpkg-assertChange related to package testify/assert

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions