aboutsummaryrefslogtreecommitdiff
path: root/lib/test
diff options
context:
space:
mode:
authorShulhan <ms@kilabit.info>2022-09-12 23:47:27 +0700
committerShulhan <ms@kilabit.info>2022-09-15 01:16:02 +0700
commitad3dbcc2b6e9e2a23fcca17df89039a660bb23bc (patch)
tree8d8ed83c063480c71960c775a8c48504262748c8 /lib/test
parent60bcaa7d75c9a17dc5a9c6349bb7b16797d6aac3 (diff)
downloadpakakeh.go-ad3dbcc2b6e9e2a23fcca17df89039a660bb23bc.tar.xz
lib/test: use text/diff to compare strings on Assert
If both exp and got types are string and its longer than 50 chars, it will use the text/diff.Text to show the difference between them. The diff output is as follow, !!! string not matched: --++ <LINE_NUM> - "<LINE_EXP>" <LINE_NUM> + "<LINE_GOT>" ^<COL_NUM> - "<DELETED_STRING>" ^<COL_NUM> + "<INSERTED_STRING>" The "<LINE_NUM> - " print the line number in exp followed by line itself. The "<LINE_NUM> + " print the line number in got followed by line itself. The "^<COL_NUM> - " show the character number in exp line followed by deleted string (or string that not exist in got). The "^<COL_NUM> + " show the character number in got line followed by inserted string (or string that not exist in exp).
Diffstat (limited to 'lib/test')
-rw-r--r--lib/test/example_test.go94
-rw-r--r--lib/test/test.go78
-rw-r--r--lib/test/test_test.go7
3 files changed, 166 insertions, 13 deletions
diff --git a/lib/test/example_test.go b/lib/test/example_test.go
index 4016fa8b..16870be3 100644
--- a/lib/test/example_test.go
+++ b/lib/test/example_test.go
@@ -7,8 +7,102 @@ package test
import (
"fmt"
"log"
+ "math/big"
)
+func ExampleAssert_struct() {
+ type ADT struct {
+ BigRat *big.Rat
+ Int int
+ Bytes []byte
+ }
+
+ var cases = []struct {
+ desc string
+ exp ADT
+ got ADT
+ }{{
+ desc: `On field struct`,
+ exp: ADT{
+ BigRat: big.NewRat(123, 456),
+ },
+ got: ADT{
+ BigRat: big.NewRat(124, 456),
+ },
+ }, {
+ desc: `On field int`,
+ exp: ADT{
+ BigRat: big.NewRat(1, 2),
+ Int: 1,
+ },
+ got: ADT{
+ BigRat: big.NewRat(1, 2),
+ Int: 2,
+ },
+ }, {
+ desc: `On field []byte`,
+ exp: ADT{
+ Bytes: []byte(`hello, world`),
+ },
+ got: ADT{
+ Bytes: []byte(`hello, world!`),
+ },
+ }, {
+ desc: `On field []byte, same length`,
+ exp: ADT{
+ Bytes: []byte(`heelo, world!`),
+ },
+ got: ADT{
+ Bytes: []byte(`hello, world!`),
+ },
+ }}
+
+ var (
+ tw = testWriter{}
+ )
+
+ for _, c := range cases {
+ Assert(&tw, c.desc, c.exp, c.got)
+ fmt.Println(tw.String())
+ tw.Reset()
+ }
+ // Output:
+ // !!! Assert: On field struct: ADT.BigRat: Rat.a: Int.abs: nat[0]: expecting Word(41), got Word(31)
+ // !!! Assert: On field int: ADT.Int: expecting int(1), got int(2)
+ // !!! Assert: On field []byte: ADT.Bytes: len(): expecting 12, got 13
+ // !!! Assert: On field []byte, same length: ADT.Bytes: [2]: expecting uint8(101), got uint8(108)
+}
+
+func ExampleAssert_string() {
+ var (
+ tw = testWriter{}
+ exp string
+ got string
+ )
+
+ exp = `a string`
+ got = `b string`
+ Assert(&tw, ``, exp, got)
+ fmt.Println(tw.String())
+
+ exp = `func (tw *testWriter) Fatal(args ...any) { fmt.Fprint(tw, args...) }`
+ got = `func (tw *testWriter) Fatalf(format string, args ...any) { fmt.Fprintf(tw, format, args...) }`
+ tw.Reset()
+ Assert(&tw, ``, exp, got)
+ fmt.Println(tw.String())
+ // Output:
+ // !!! Assert: expecting string(a string), got string(b string)
+ // !!! strings not matched:
+ // --++
+ // 0 - "func (tw *testWriter) Fatal(args ...any) { fmt.Fprint(tw, args...) }"
+ // 0 + "func (tw *testWriter) Fatalf(format string, args ...any) { fmt.Fprintf(tw, format, args...) }"
+ // ^27 - "("
+ // ^41 - " "
+ // ^27 + "f(format string, "
+ // ^69 + "f"
+ // ^56 + ", format"
+}
+
func ExampleLoadDataDir() {
var (
listData []*Data
diff --git a/lib/test/test.go b/lib/test/test.go
index bf4413d6..5435ca06 100644
--- a/lib/test/test.go
+++ b/lib/test/test.go
@@ -9,6 +9,7 @@ import (
"runtime"
"github.com/shuLhan/share/lib/reflect"
+ "github.com/shuLhan/share/lib/text/diff"
)
func printStackTrace(w Writer, trace []byte) {
@@ -40,17 +41,43 @@ func printStackTrace(w Writer, trace []byte) {
}
}
-// Assert compare two interfaces: `exp` and `got` for equality.
-// If both parameters are not equal, the function will call Fatalf that
-// describe the position (type and value) where value are not matched.
+// Assert compare two interfaces: exp and got for equality.
+// If both parameters are not equal, the function will call print and try to
+// describe the position (type and value) where value are not matched and call
+// Fatalf.
//
-// If `exp` implement the extended `reflect.Equaler`, then it will use the
-// method `IsEqual()` with `got` as parameter.
+// If exp implement the extended reflect.Equaler, then it will use the
+// method IsEqual with got as parameter.
+//
+// If exp and got is a struct, it will print the first non-matched field in
+// the following format,
+//
+// !!! Assert: [<name>: ] T.<Field>: expecting <type>(<value>), got <type>(<value>)
+//
+// If both exp and got types are string and its longer than 50 chars, it
+// will use the text/diff.Text to show the difference between them.
+// The diff output is as follow,
+//
+// !!! string not matched:
+// --++
+// <LINE_NUM> - "<LINE_EXP>"
+// <LINE_NUM> + "<LINE_GOT>"
+// ^<COL_NUM> - "<DELETED_STRING>"
+// ^<COL_NUM> + "<INSERTED_STRING>"
+//
+// The "<LINE_NUM> - " print the line number in exp followed by line itself.
+// The "<LINE_NUM> + " print the line number in got followed by line itself.
+// The "^<COL_NUM> - " show the character number in exp line followed by
+// deleted string (or string that not exist in got).
+// The "^<COL_NUM> + " show the character number in got line followed by
+// inserted string (or string that not exist in exp).
//
// WARNING: this method does not support recursive pointer, for example a node
// that point to parent and parent that point back to node again.
func Assert(w Writer, name string, exp, got interface{}) {
var (
+ logp = `Assert`
+
err error
trace []byte
)
@@ -64,9 +91,46 @@ func Assert(w Writer, name string, exp, got interface{}) {
runtime.Stack(trace, false)
printStackTrace(w, trace)
+ if printStringDiff(w, name, exp, got) {
+ return
+ }
+
if len(name) == 0 {
- w.Fatalf(`!!! %s`, err)
+ w.Fatalf(`!!! %s: %s`, logp, err)
} else {
- w.Fatalf(`!!! %s: %s`, name, err)
+ w.Fatalf(`!!! %s: %s: %s`, logp, name, err)
}
}
+
+func printStringDiff(w Writer, name string, exp, got interface{}) bool {
+ var (
+ diffData diff.Data
+ expStr string
+ gotStr string
+ ok bool
+ )
+
+ expStr, ok = exp.(string)
+ if !ok {
+ return false
+ }
+
+ gotStr, ok = got.(string)
+ if !ok {
+ return false
+ }
+
+ if len(expStr) < 50 {
+ return false
+ }
+
+ diffData = diff.Text([]byte(expStr), []byte(gotStr), diff.LevelWords)
+
+ if len(name) == 0 {
+ w.Log("!!! strings not matched:\n", diffData.String())
+ } else {
+ w.Logf("!!! %s:\n%s", name, diffData.String())
+ }
+
+ return true
+}
diff --git a/lib/test/test_test.go b/lib/test/test_test.go
index 9f1e1c14..e25d5f6b 100644
--- a/lib/test/test_test.go
+++ b/lib/test/test_test.go
@@ -22,12 +22,7 @@ func TestAssert(t *testing.T) {
desc: `nil interface{}`,
a: nil,
b: &str,
- exp: `!!! DoEqual: IsValid: expecting <invalid Value>(false), got <*string Value>(true)`,
- }, {
- desc: `short string`,
- a: `a string`,
- b: `b string`,
- exp: `!!! DoEqual: expecting string(a string), got string(b string)`,
+ exp: `!!! Assert: IsValid: expecting <invalid Value>(false), got <*string Value>(true)`,
}}
var (