Giter Site home page Giter Site logo

expect's Introduction

Expect.go Build status License GoDoc

Minimalistic BDD-style assertions for Go (inspired by expect.js)

expect := expect.New(t)

// Numbers
expect(10).To.Be.Above(1).And.Below(20)
expect(5).Not.To.Be.Within(0, 4)

// Strings
expect("foobarbaz").To.StartWith("foo").And.EndWith("baz").And.Contains("bar")
expect("Foo").To.Match("(?i)foo")

// Equal
expect(res.StatusCode).To.Equal(200)
expect(false).Not.To.Equal("false")
expect(map[int]int{}).To.Equal(map[int]int{})

// Empty
expect(map[int]int{}).To.Be.Empty()
expect("").To.Be.Empty()
expect([2]int{}).Not.To.Be.Empty()

// Ok (i.e: not "", 0, false, nil)
expect(val).To.Be.Ok()
expect(false).Not.To.Be.Ok()

// True/False
expect(true).To.Be.True()
expect(false).To.Be.False()

// Type Assertion
expect("").To.Be.String()
expect(0).To.Be.Int()
expect(1.1).To.Be.Float()
expect(1).Not.To.Be.Bool()
expect(map[string]int{}).To.Be.Map()
expect([...]int{1}).To.Be.Array()
expect([]string{"a"}).To.Be.Slice()
expect(ch).To.Be.Chan()
expect(struct{}{}).To.Be.Struct()
expect(&struct{}{}).To.Be.Ptr()
expect(nil).To.Be.Nil()
expect(Person{}).To.Be.Type("Person")

// Len
expect("foo").To.Have.Len(3)
expect([]int{1, 2}).To.Have.Len(2)

// Cap
expect(make([]byte, 2, 10)).To.Have.Cap(10)
expect([2]int{}).To.Have.Cap(2)

// Maps
m1 := map[string]int{
	"a": 1,
	"b": 2,
}
expect(m1).To.Have.Key("a")
expect(m1).To.Have.Key("a", 1) // With value
expect(m1).To.Have.Keys("a", "b")

// Structs
p := struct {
	X, Y int
}{1, 3}
expect(p).To.Have.Field("Y", 3).And.Field("X", 1)

// Functions
expect(func() {}).Not.To.Panic()
expect(func() {
	panic("foo")
}).To.Panic()
expect(func() {
	panic("bar")
}).To.Panic("bar")

// FailNow
expect("foo").To.Equal("bar").Else.FailNow()

License

MIT

expect's People

Contributors

a8m avatar jasonkeene avatar nelsam avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

expect's Issues

CI

Travis & Coveralls

Else is Naive

expect("foo").To.Equal("bar").And.Be.String().Else.FailNow() won't actually FailNow(), as you would expect it to.

Matcher for reading from channels

Often we are asserting on reading from a channel. It would be useful to have one that could read from channel and make further assertions on the result.

e.g.

c := make(chan int, 100)
// ...
expect(c).To.Receive().And.Equal(90)

This example has more than just the Receive functionality. It also includes some chaining. If is distasteful, then maybe the following would be more palatable:

c := make(chan int, 100)
// ...
expect(c).To.Receive(&i).Else.FailNow()
expect(i).To.Equal(90)

Include More Stack Info

Right now, failures are kind of obtuse:

--- FAIL: TestEndWith (0.00s)
    to.go:33: Expect bar to end with az
FAIL
exit status 1
FAIL    github.com/a8m/expect   0.002s

Having a fuller stack trace would help narrow down errors, especially when helper functions are employed. Example output:

--- FAIL: TestEndWith (0.00s)
    /usr/lib/go/src/testing/testing.go:610
    /home/valczir/dev/expect/src/github.com/a8m/expect/to_test.go:17
    /home/valczir/dev/expect/src/github.com/a8m/expect/to.go:33
        Expect bar to end with az
FAIL
exit status 1
FAIL    github.com/a8m/expect   0.003s

Fail Fast (sometimes)

There are often times when I need to fail a test early to prevent it from running checks against invalid data. A simple example:

func TestSomething(t *testing.T) {
    expect := expect.New(t)
    t, err := foo.NewT()
    expect(err).To.Be.Nil()

    // If the previous assertion failed, with err being non-nil,
    // then the following assertion will panic on a nil pointer
    // dereference.
    expect(t.Foo).To.Equal("foo")
}

I'd like to be able to ask expect to call FailNow() on a failure. Something like:

func TestSomething(t *testing.T) {
    expect := expect.New(t)
    t, err := foo.NewT()
    expect(err).To.Be.Nil().Else.FailNow()

    // At this point, we know that err was nil, because we
    // won't get here if it's not.
    expect(t.Foo).To.Equal("foo")
}

Custom Assertions

If I have a very special case assertion to make and I don't want to repeat it everywhere, I'd like to write my own matcher of some sort and be able to pass it in to expect. Something like:

type ResponseCodeMatcher int

func (r ResponseCodeMatcher) Match(actual interface{}) error {
    resp, ok := actual.(*http.Response)
    if !ok {
        return errors.New("be of type *http.Response")
    }
    if resp.StatusCode != int(r) {
        return fmt.Errorf("have a status code of %d", r)
    }
    return nil
}

func TestSomething(t *testing.T) {
    // somehow we get a *http.Response
    expect(resp).To.Pass(ResponseCodeMatcher(http.StatusOK))
}

LICENSE file

There's now a license badge, but we don't yet have a LICENSE file. The badge tries to link to a file, but the file doesn't exist.

Chaining doesn't bail out

If you have:

expect("a").
  To.Equal("b").
  And.Pass(SomeMatcher{}) // <- Should this not run?

I wouldn't expect the And.Pass(...) to be invoked.

panic

expect(fn).To.Panic()

Eventually / Consistently?

I'm coming from ginkgo/gomega. I still use those at work, but I just can't bring myself to use it at home. I don't trust libraries that hide so much of how go test works behind weird black magic, nor anything with as many aliases as gomega has (I came from python, so I like there to be exactly one obvious way to do any given thing).

That said, I do miss some of that functionality from time to time. Right now, the one I'm missing the most is consistently/eventually - e.g. expect(func() int { return time.Now().Unix() % 10 }).To.Eventually.Return(7) and expect(func() int { return 3 }).To.Consistently.Return(3), maybe include Receive and Have.Len for channels (although Consistently's Receive should only work for checking that a channel does not receive - checking that a channel consistently receives just doesn't make sense). What would you think of supporting that, @a8m?

I can write it (the functionality isn't really too hard), but I didn't want to go that route if it's more complicated than expect is aiming for.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.