stretchr / testify

A toolkit with common assertions and mocks that plays nicely with the standard library
MIT License
22.5k stars 1.56k forks source link

Should `Equal` pass too when `EqualValues` would pass? #235

Open ernesto-jimenez opened 8 years ago

ernesto-jimenez commented 8 years ago

Right now there are some cases where Equals fails where EqualValues passes. e.g: comparing assert.Equal(t, uint32(5), 5)

However, Equal is a broader term and seems to imply that it would include EqualValues.

I want to consider making Equal pass when EqualValues passes too.

Main thing to research is whether there's any case where that behaviour would translate in an Equal assertion passing when it should be failing.

ernesto-jimenez commented 8 years ago

/cc @TechnotronicOz

greenboxal commented 8 years ago

This also happens in a worse case, when comparing a "enum" variable to a literal constant of that enum, as follow:

type MyEnum int
const (
    _ MyEnum = iota
    Enum1 = iota
    Enum2 = iota
)

func TestIt(t *testing.T) {
    a := Enum1

    assert.Equal(t, a, Enum1, "Enum1 = Enum1")
}

This code fails saying that Enum1 != Enum1. Seems like Go takes that typed constant and flattens its type to int and thus reflect.DeepEqual fails.

ernesto-jimenez commented 8 years ago

@greenboxal, that test does pass properly. What version of testify are you using?

=== RUN   TestIt
--- PASS: TestIt (0.00s)
PASS
georgelesica-wf commented 5 years ago

We should determine whether or not this is still the case and investigate accordingly.

zach-skysafe commented 4 years ago

Using v1.4.0, I can replicate the error this way.

type MyEnum int
const (
    Enum1 MyEnum = 1
    Enum2 = 2
)

func TestIt(t *testing.T) {
     assert := assert.New(t)

     var a MyEnum = Enum2

     assert.True(a == Enum2)
     assert.EqualValues(Enum2, a)
     assert.Equal(Enum2, a)
}

The assert.True passes, assert.EqualValues passes, but the assert.Equal calls fails. If you change the enum definition to

type MyEnum int
const (
     Enum1 MyEnum = 1
     Enum2 MyEnum = 2
)

Equal doesn't have a problem.

Nokel81 commented 4 years ago

@zach-skysafe That is because the following code

package main

import (
    "fmt"
    "reflect"
)

type MyEnum int
const (
    Enum1 MyEnum = 1
    Enum2 = 2
)

func main() {
    fmt.Println(reflect.TypeOf(Enum1).Name())
    fmt.Println(reflect.TypeOf(Enum2).Name())
}

Outputs the following:

MyEnum
int

The correct way to specify the enum would be to do:

type MyEnum int
const (
    Enum1 MyEnum = iota
    Enum2
)
zach-skysafe commented 4 years ago

Replace with

type MyEnum string
const (
    Enum1 MyEnum = "first"
    Enum2 = "second"
)

And you'll see the same error. I'm just providing an example case of when Equal and EqualValues don't match. Seeing as the builtin == also passes, I would expect Equal to pass as well.

I can understand the argument either way in this case. IMHO, this is dealing with a weakness in golang itself. So coding around that is probably not going to satisfy everyone.

Another way to look at the question of Equal vs EqualValue; if there are two different functions, I would expect them to have a difference. If they both evaluate with the same logic, why have 2 functions? I also just saw now that there is an Exactly function, which appears to work the same as Equals in all the test cases in this thread.

Nokel81 commented 4 years ago

I think that Equal here shouldn't pass since they are not the same type (string vs MyEnum). And that is why there is the EqualValue function.

Another way to look at the question of Equal vs EqualValue; if there are two different functions, I would expect them to have a difference. If they both evaluate with the same logic, why have 2 functions? I also just saw now that there is an Exactly function, which appears to work the same as Equals in all the test cases in this thread.

Exactly, they don't evaluate to the same logic since Equal requires that the types are the same.

zach-skysafe commented 4 years ago

I would understand Exactly not passing, since it specifies "Exactly asserts that two objects are equal in value and type."

Equal is just commented "Equal asserts that two objects are equal", which is ambiguous. Is it intended to be similar to Exactly, or are there distinctions for other cases?

jteppinette commented 1 year ago

Can anyone clarify the difference between Exactly and Equal?