A package for assertions without dependency hell
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

177 lines
4.4 KiB

  1. package assert
  2. import (
  3. "reflect"
  4. "github.com/google/go-cmp/cmp"
  5. )
  6. // Assert is a helper for tests
  7. type Assert struct {
  8. t T
  9. }
  10. func (a Assert) f(ok bool, msg []interface{}, format string, extra ...interface{}) {
  11. if !ok {
  12. if format != `` {
  13. msg = prepMsg(msg, format, extra...)
  14. }
  15. if msg == nil {
  16. msg = []interface{}{`Assertion failed`}
  17. }
  18. msg = append(append([]interface{}{shell(1) + shell(97) + shell(41) + `FAIL!` + shell(0) + shell(1)}, msg...), shell(0), "\n")
  19. a.t.Helper()
  20. a.t.Error(msg...)
  21. }
  22. }
  23. // New returns a new Assert
  24. func New(t T) Assert {
  25. a := Assert{t}
  26. return a
  27. }
  28. // TODO: Panics, Len
  29. ///// Boolean /////
  30. // True asserts the given value is true
  31. func (a Assert) True(actual bool, msg ...interface{}) {
  32. a.t.Helper()
  33. a.f(actual, msg, `Should be true, but it isn't`)
  34. }
  35. // False asserts the given value is false
  36. func (a Assert) False(actual bool, msg ...interface{}) {
  37. a.t.Helper()
  38. a.f(!actual, msg, `Should be false, but it isn't`)
  39. }
  40. ///// Nil /////
  41. func isNil(val interface{}) bool {
  42. if val == nil {
  43. return true
  44. }
  45. v := reflect.ValueOf(val)
  46. switch v.Kind() {
  47. case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
  48. return v.IsNil()
  49. }
  50. return false
  51. }
  52. // Nil asserts the given value is nil
  53. func (a Assert) Nil(actual interface{}, msg ...interface{}) {
  54. a.t.Helper()
  55. a.f(isNil(actual), msg, `Should be nil, but got %#v`, actual)
  56. }
  57. // NotNil asserts the given value is not nil
  58. func (a Assert) NotNil(actual interface{}, msg ...interface{}) {
  59. a.t.Helper()
  60. a.f(!isNil(actual), msg, `Should not be nil, but it is`)
  61. }
  62. ///// Errors /////
  63. // Error asserts the given error is not nil
  64. func (a Assert) Error(actual error, msg ...interface{}) {
  65. a.t.Helper()
  66. a.f(actual != nil, msg, `Expected an error, but got nil`)
  67. }
  68. // NoError asserts the given error is nil
  69. func (a Assert) NoError(actual error, msg ...interface{}) {
  70. a.t.Helper()
  71. a.f(actual == nil, msg, `Expected no error, but got %#v`, actual)
  72. }
  73. ///// Comparisons /////
  74. // Eq asserts the given values match
  75. func (a Assert) Eq(expected, actual interface{}, msg ...interface{}) {
  76. a.t.Helper()
  77. if reflect.TypeOf(expected) != reflect.TypeOf(actual) {
  78. a.f(false, msg, `Expected %T(%#v), but got %T(%#v)`, expected, expected, actual, actual)
  79. return
  80. }
  81. a.f(expected == actual, msg, `Expected %#v, but got %#v`, expected, actual)
  82. }
  83. // Ne asserts the given values don't match
  84. func (a Assert) Ne(expected, actual interface{}, msg ...interface{}) {
  85. a.t.Helper()
  86. a.f(expected != actual, msg, `Should not be %#v, but it is`, expected)
  87. }
  88. ///// Lists /////
  89. // Contains asserts the expected value is in the given list
  90. func (a Assert) Contains(expected, list interface{}, msg ...interface{}) {
  91. a.t.Helper()
  92. rlist := reflect.ValueOf(list)
  93. a.f(rlist.Kind() == reflect.Slice || rlist.Kind() == reflect.Array, nil, `Can only call assert.Contains on a slice or array`)
  94. for i := 0; i < rlist.Len(); i++ {
  95. if rlist.Index(i).Interface() == expected {
  96. return
  97. }
  98. }
  99. a.f(false, msg, `Expected %#v to be in %#v, but it isn't`, expected, list)
  100. }
  101. // SameElements asserts the values have the same elements. It ignores the order of the elements
  102. func (a Assert) SameElements(expected, actual interface{}, msg ...interface{}) {
  103. a.t.Helper()
  104. rexpected, ractual := reflect.ValueOf(expected), reflect.ValueOf(actual)
  105. a.f(rexpected.Kind() == reflect.Slice || rexpected.Kind() == reflect.Array, nil, `Can only call assert.SameElements on a slice or array`)
  106. a.f(ractual.Kind() == reflect.Slice || ractual.Kind() == reflect.Array, nil, `Can only call assert.SameElements on a slice or array`)
  107. if rexpected.Len() != ractual.Len() {
  108. a.f(false, msg, `Expected elements of %#v to match %#v, but they don't`, expected, actual)
  109. return
  110. }
  111. var same int
  112. for i := 0; i < rexpected.Len(); i++ {
  113. for j := 0; j < ractual.Len(); j++ {
  114. if rexpected.Index(i).Interface() == ractual.Index(j).Interface() {
  115. same++
  116. break
  117. }
  118. }
  119. }
  120. if same == rexpected.Len() {
  121. return
  122. }
  123. a.f(false, msg, ``)
  124. }
  125. // Cmp assert wrapper for go-cmp
  126. func (a Assert) Cmp(expected, actual interface{}, opts ...cmp.Option) {
  127. a.t.Helper()
  128. diff := cmp.Diff(expected, actual, opts...)
  129. if diff == `` {
  130. return
  131. }
  132. a.f(false, nil, "\n"+diff)
  133. }
  134. // NCmp assert wrapper for go-cmp but fails when !Equal
  135. func (a Assert) NCmp(expected, actual interface{}, opts ...cmp.Option) {
  136. a.t.Helper()
  137. ok := cmp.Equal(expected, actual, opts...)
  138. a.f(!ok, nil, `Should not be %#v, but it is`, expected)
  139. }