...

Source file src/gotest.tools/v3/assert/assert.go

Documentation: gotest.tools/v3/assert

     1  /*
     2  Package assert provides assertions for comparing expected values to actual
     3  values in tests. When an assertion fails a helpful error message is printed.
     4  
     5  # Example usage
     6  
     7  All the assertions in this package use [testing.T.Helper] to mark themselves as
     8  test helpers. This allows the testing package to print the filename and line
     9  number of the file function that failed.
    10  
    11  	assert.NilError(t, err)
    12  	// filename_test.go:212: assertion failed: error is not nil: file not found
    13  
    14  If any assertion is called from a helper function, make sure to call t.Helper
    15  from the helper function so that the filename and line number remain correct.
    16  
    17  The examples below show assert used with some common types and the failure
    18  messages it produces. The filename and line number portion of the failure
    19  message is omitted from these examples for brevity.
    20  
    21  	// booleans
    22  
    23  	assert.Assert(t, ok)
    24  	// assertion failed: ok is false
    25  	assert.Assert(t, !missing)
    26  	// assertion failed: missing is true
    27  
    28  	// primitives
    29  
    30  	assert.Equal(t, count, 1)
    31  	// assertion failed: 0 (count int) != 1 (int)
    32  	assert.Equal(t, msg, "the message")
    33  	// assertion failed: my message (msg string) != the message (string)
    34  	assert.Assert(t, total != 10) // use Assert for NotEqual
    35  	// assertion failed: total is 10
    36  	assert.Assert(t, count > 20, "count=%v", count)
    37  	// assertion failed: count is <= 20: count=1
    38  
    39  	// errors
    40  
    41  	assert.NilError(t, closer.Close())
    42  	// assertion failed: error is not nil: close /file: errno 11
    43  	assert.Error(t, err, "the exact error message")
    44  	// assertion failed: expected error "the exact error message", got "oops"
    45  	assert.ErrorContains(t, err, "includes this")
    46  	// assertion failed: expected error to contain "includes this", got "oops"
    47  	assert.ErrorIs(t, err, os.ErrNotExist)
    48  	// assertion failed: error is "oops", not "file does not exist" (os.ErrNotExist)
    49  
    50  	// complex types
    51  
    52  	assert.DeepEqual(t, result, myStruct{Name: "title"})
    53  	// assertion failed: ... (diff of the two structs)
    54  	assert.Assert(t, is.Len(items, 3))
    55  	// assertion failed: expected [] (length 0) to have length 3
    56  	assert.Assert(t, len(sequence) != 0) // use Assert for NotEmpty
    57  	// assertion failed: len(sequence) is 0
    58  	assert.Assert(t, is.Contains(mapping, "key"))
    59  	// assertion failed: map[other:1] does not contain key
    60  
    61  	// pointers and interface
    62  
    63  	assert.Assert(t, ref == nil)
    64  	// assertion failed: ref is not nil
    65  	assert.Assert(t, ref != nil) // use Assert for NotNil
    66  	// assertion failed: ref is nil
    67  
    68  # Assert and Check
    69  
    70  [Assert] and [Check] are very similar, they both accept a [cmp.Comparison], and fail
    71  the test when the comparison fails. The one difference is that Assert uses
    72  [testing.T.FailNow] to fail the test, which will end the test execution immediately.
    73  Check uses [testing.T.Fail] to fail the test, which allows it to return the
    74  result of the comparison, then proceed with the rest of the test case.
    75  
    76  Like [testing.T.FailNow], [Assert] must be called from the goroutine running the test,
    77  not from other goroutines created during the test. [Check] is safe to use from any
    78  goroutine.
    79  
    80  # Comparisons
    81  
    82  Package [gotest.tools/v3/assert/cmp] provides
    83  many common comparisons. Additional comparisons can be written to compare
    84  values in other ways. See the example Assert (CustomComparison).
    85  
    86  # Automated migration from testify
    87  
    88  gty-migrate-from-testify is a command which translates Go source code from
    89  testify assertions to the assertions provided by this package.
    90  
    91  See http://pkg.go.dev/gotest.tools/v3/assert/cmd/gty-migrate-from-testify.
    92  */
    93  package assert // import "gotest.tools/v3/assert"
    94  
    95  import (
    96  	gocmp "github.com/google/go-cmp/cmp"
    97  	"gotest.tools/v3/assert/cmp"
    98  	"gotest.tools/v3/internal/assert"
    99  )
   100  
   101  // BoolOrComparison can be a bool, [cmp.Comparison], or error. See [Assert] for
   102  // details about how this type is used.
   103  type BoolOrComparison interface{}
   104  
   105  // TestingT is the subset of [testing.T] (see also [testing.TB]) used by the assert package.
   106  type TestingT interface {
   107  	FailNow()
   108  	Fail()
   109  	Log(args ...interface{})
   110  }
   111  
   112  type helperT interface {
   113  	Helper()
   114  }
   115  
   116  // Assert performs a comparison. If the comparison fails, the test is marked as
   117  // failed, a failure message is logged, and execution is stopped immediately.
   118  //
   119  // The comparison argument may be one of three types:
   120  //
   121  //	bool
   122  //	  True is success. False is a failure. The failure message will contain
   123  //	  the literal source code of the expression.
   124  //
   125  //	cmp.Comparison
   126  //	  Uses cmp.Result.Success() to check for success or failure.
   127  //	  The comparison is responsible for producing a helpful failure message.
   128  //	  http://pkg.go.dev/gotest.tools/v3/assert/cmp provides many common comparisons.
   129  //
   130  //	error
   131  //	  A nil value is considered success, and a non-nil error is a failure.
   132  //	  The return value of error.Error is used as the failure message.
   133  //
   134  // Extra details can be added to the failure message using msgAndArgs. msgAndArgs
   135  // may be either a single string, or a format string and args that will be
   136  // passed to [fmt.Sprintf].
   137  //
   138  // Assert uses [testing.TB.FailNow] to fail the test. Like t.FailNow, Assert must be called
   139  // from the goroutine running the test function, not from other
   140  // goroutines created during the test. Use [Check] from other goroutines.
   141  func Assert(t TestingT, comparison BoolOrComparison, msgAndArgs ...interface{}) {
   142  	if ht, ok := t.(helperT); ok {
   143  		ht.Helper()
   144  	}
   145  	if !assert.Eval(t, assert.ArgsFromComparisonCall, comparison, msgAndArgs...) {
   146  		t.FailNow()
   147  	}
   148  }
   149  
   150  // Check performs a comparison. If the comparison fails the test is marked as
   151  // failed, a failure message is printed, and Check returns false. If the comparison
   152  // is successful Check returns true. Check may be called from any goroutine.
   153  //
   154  // See [Assert] for details about the comparison arg and failure messages.
   155  func Check(t TestingT, comparison BoolOrComparison, msgAndArgs ...interface{}) bool {
   156  	if ht, ok := t.(helperT); ok {
   157  		ht.Helper()
   158  	}
   159  	if !assert.Eval(t, assert.ArgsFromComparisonCall, comparison, msgAndArgs...) {
   160  		t.Fail()
   161  		return false
   162  	}
   163  	return true
   164  }
   165  
   166  // NilError fails the test immediately if err is not nil, and includes err.Error
   167  // in the failure message.
   168  //
   169  // NilError uses [testing.TB.FailNow] to fail the test. Like t.FailNow, NilError must be
   170  // called from the goroutine running the test function, not from other
   171  // goroutines created during the test. Use [Check] from other goroutines.
   172  func NilError(t TestingT, err error, msgAndArgs ...interface{}) {
   173  	if ht, ok := t.(helperT); ok {
   174  		ht.Helper()
   175  	}
   176  	if !assert.Eval(t, assert.ArgsAfterT, err, msgAndArgs...) {
   177  		t.FailNow()
   178  	}
   179  }
   180  
   181  // Equal uses the == operator to assert two values are equal and fails the test
   182  // if they are not equal.
   183  //
   184  // If the comparison fails Equal will use the variable names and types of
   185  // x and y as part of the failure message to identify the actual and expected
   186  // values.
   187  //
   188  //	assert.Equal(t, actual, expected)
   189  //	// main_test.go:41: assertion failed: 1 (actual int) != 21 (expected int32)
   190  //
   191  // If either x or y are a multi-line string the failure message will include a
   192  // unified diff of the two values. If the values only differ by whitespace
   193  // the unified diff will be augmented by replacing whitespace characters with
   194  // visible characters to identify the whitespace difference.
   195  //
   196  // Equal uses [testing.T.FailNow] to fail the test. Like t.FailNow, Equal must be
   197  // called from the goroutine running the test function, not from other
   198  // goroutines created during the test. Use [Check] with [cmp.Equal] from other
   199  // goroutines.
   200  func Equal(t TestingT, x, y interface{}, msgAndArgs ...interface{}) {
   201  	if ht, ok := t.(helperT); ok {
   202  		ht.Helper()
   203  	}
   204  	if !assert.Eval(t, assert.ArgsAfterT, cmp.Equal(x, y), msgAndArgs...) {
   205  		t.FailNow()
   206  	}
   207  }
   208  
   209  // DeepEqual uses [github.com/google/go-cmp/cmp]
   210  // to assert two values are equal and fails the test if they are not equal.
   211  //
   212  // Package [gotest.tools/v3/assert/opt] provides some additional
   213  // commonly used Options.
   214  //
   215  // DeepEqual uses [testing.T.FailNow] to fail the test. Like t.FailNow, DeepEqual must be
   216  // called from the goroutine running the test function, not from other
   217  // goroutines created during the test. Use [Check] with [cmp.DeepEqual] from other
   218  // goroutines.
   219  func DeepEqual(t TestingT, x, y interface{}, opts ...gocmp.Option) {
   220  	if ht, ok := t.(helperT); ok {
   221  		ht.Helper()
   222  	}
   223  	if !assert.Eval(t, assert.ArgsAfterT, cmp.DeepEqual(x, y, opts...)) {
   224  		t.FailNow()
   225  	}
   226  }
   227  
   228  // Error fails the test if err is nil, or if err.Error is not equal to expected.
   229  // Both err.Error and expected will be included in the failure message.
   230  // Error performs an exact match of the error text. Use [ErrorContains] if only
   231  // part of the error message is relevant. Use [ErrorType] or [ErrorIs] to compare
   232  // errors by type.
   233  //
   234  // Error uses [testing.T.FailNow] to fail the test. Like t.FailNow, Error must be
   235  // called from the goroutine running the test function, not from other
   236  // goroutines created during the test. Use [Check] with [cmp.Error] from other
   237  // goroutines.
   238  func Error(t TestingT, err error, expected string, msgAndArgs ...interface{}) {
   239  	if ht, ok := t.(helperT); ok {
   240  		ht.Helper()
   241  	}
   242  	if !assert.Eval(t, assert.ArgsAfterT, cmp.Error(err, expected), msgAndArgs...) {
   243  		t.FailNow()
   244  	}
   245  }
   246  
   247  // ErrorContains fails the test if err is nil, or if err.Error does not
   248  // contain the expected substring. Both err.Error and the expected substring
   249  // will be included in the failure message.
   250  //
   251  // ErrorContains uses [testing.T.FailNow] to fail the test. Like t.FailNow, ErrorContains
   252  // must be called from the goroutine running the test function, not from other
   253  // goroutines created during the test. Use [Check] with [cmp.ErrorContains] from other
   254  // goroutines.
   255  func ErrorContains(t TestingT, err error, substring string, msgAndArgs ...interface{}) {
   256  	if ht, ok := t.(helperT); ok {
   257  		ht.Helper()
   258  	}
   259  	if !assert.Eval(t, assert.ArgsAfterT, cmp.ErrorContains(err, substring), msgAndArgs...) {
   260  		t.FailNow()
   261  	}
   262  }
   263  
   264  // ErrorType fails the test if err is nil, or err is not the expected type.
   265  // New code should use ErrorIs instead.
   266  //
   267  // Expected can be one of:
   268  //
   269  //	func(error) bool
   270  //	  The function should return true if the error is the expected type.
   271  //
   272  //	struct{} or *struct{}
   273  //	  A struct or a pointer to a struct. The assertion fails if the error is
   274  //	  not of the same type.
   275  //
   276  //	*interface{}
   277  //	  A pointer to an interface type. The assertion fails if err does not
   278  //	  implement the interface.
   279  //
   280  //	reflect.Type
   281  //	  The assertion fails if err does not implement the reflect.Type.
   282  //
   283  // ErrorType uses [testing.T.FailNow] to fail the test. Like t.FailNow, ErrorType
   284  // must be called from the goroutine running the test function, not from other
   285  // goroutines created during the test. Use [Check] with [cmp.ErrorType] from other
   286  // goroutines.
   287  func ErrorType(t TestingT, err error, expected interface{}, msgAndArgs ...interface{}) {
   288  	if ht, ok := t.(helperT); ok {
   289  		ht.Helper()
   290  	}
   291  	if !assert.Eval(t, assert.ArgsAfterT, cmp.ErrorType(err, expected), msgAndArgs...) {
   292  		t.FailNow()
   293  	}
   294  }
   295  
   296  // ErrorIs fails the test if err is nil, or the error does not match expected
   297  // when compared using errors.Is. See [errors.Is] for
   298  // accepted arguments.
   299  //
   300  // ErrorIs uses [testing.T.FailNow] to fail the test. Like t.FailNow, ErrorIs
   301  // must be called from the goroutine running the test function, not from other
   302  // goroutines created during the test. Use [Check] with [cmp.ErrorIs] from other
   303  // goroutines.
   304  func ErrorIs(t TestingT, err error, expected error, msgAndArgs ...interface{}) {
   305  	if ht, ok := t.(helperT); ok {
   306  		ht.Helper()
   307  	}
   308  	if !assert.Eval(t, assert.ArgsAfterT, cmp.ErrorIs(err, expected), msgAndArgs...) {
   309  		t.FailNow()
   310  	}
   311  }
   312  

View as plain text