├── .github ├── CONTRIBUTING.md ├── issue_template.md ├── pull_request_template.md └── workflows │ └── go.yml ├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── appveyor.yml ├── assert.go ├── circle.yml ├── cov.go ├── dbg.go ├── example ├── add.go └── add_test.go ├── fn.go ├── go.mod ├── http.go ├── http └── http.go ├── mock └── mock.go ├── sql.go ├── tt.go └── tt_test.go /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Ego 2 | 3 | -------------------------------------------------------------------------------- /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | 1. Please **speak English**, this is the language everybody of us can speak and write. 2 | 2. Please take a moment to **search** that an issue **doesn't already exist**. 3 | 3. Please ask questions or config/deploy problems on our Gitter channel: https://gitter.im/go-ego/ego 4 | 4. Please give all relevant information below for bug reports, incomplete details will be handled as an invalid report. 5 | 6 | **You MUST delete the content above including this line before posting, otherwise your issue will be invalid.** 7 | 8 | - Tt version (or commit ref): 9 | - Go version: 10 | 11 | - Operating system and bit: 12 | - Can you reproduce the bug at [Examples](https://github.com/vcaesar/tt/tree/master/examples): 13 | - [ ] Yes (provide example code) 14 | - [ ] No 15 | - [ ] Not relevant 16 | - Provide example code: 17 | 18 | ```Go 19 | 20 | ``` 21 | - Log gist: 22 | 23 | ## Description 24 | 25 | ... 26 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | The pull request will be closed without any reasons if it does not satisfy any of following requirements: 2 | 3 | 1. Make sure you are targeting the `master` branch, pull requests on release branches are only allowed for bug fixes. 4 | 2. Add new features, please provide the reasons and test code. 5 | 3. Please read contributing guidelines: [CONTRIBUTING](https://github.com/vcaesar/tt/blob/master/CONTRIBUTING.md) 6 | 4. Describe what your pull request does and which issue you're targeting (if any and Please use English) 7 | 5. ... if it is not related to any particular issues, explain why we should not reject your pull request. 8 | 6. The Commits must use English, must be test and No useless submissions. 9 | 10 | **You MUST delete the content above including this line before posting, otherwise your pull request will be invalid.** 11 | 12 | **Please provide Issues links to:** 13 | 14 | - Issues: #1 15 | 16 | **Provide test code:** 17 | 18 | ```Go 19 | 20 | ``` 21 | 22 | ## Description 23 | 24 | ... 25 | -------------------------------------------------------------------------------- /.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | name: Go 2 | on: [push] 3 | jobs: 4 | test: 5 | # name: build 6 | strategy: 7 | matrix: 8 | go: [1.23.x, 1.24.x] 9 | os: [macOS-latest, windows-latest, ubuntu-latest] 10 | runs-on: ${{ matrix.os }} 11 | 12 | steps: 13 | - name: Set up Go ${{ matrix.go }} 14 | uses: actions/setup-go@v1 15 | with: 16 | go-version: ${{ matrix.go }} 17 | id: go 18 | 19 | - name: Check out code into the Go module directory 20 | uses: actions/checkout@v1 21 | 22 | - name: Get dependencies 23 | run: | 24 | go get -v -t -d ./... 25 | 26 | - name: Build 27 | run: go build -v . 28 | - name: Test 29 | run: go test -v . 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | .DS_Store 3 | .vscode 4 | .idea 5 | 6 | # Binaries for programs and plugins 7 | *.exe 8 | *.dll 9 | *.so 10 | *.dylib 11 | 12 | # Test binary, build with `go test -c` 13 | *.test 14 | 15 | # Output of the go coverage tool, specifically when used with LiteIDE 16 | *.out 17 | 18 | # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 19 | .glide/ 20 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go_import_path: github.com/vcaesar/tt 4 | 5 | go: 6 | # - 1.8.x 7 | # - 1.9.x 8 | # - 1.10.x 9 | # - 1.11.x 10 | # - 1.12.x 11 | # - 1.13.x 12 | # - 1.14.x 13 | # - 1.15.x 14 | # - 1.16.x 15 | # - 1.17.x 16 | # - 1.18.x 17 | - 1.19.x 18 | # - tip 19 | 20 | install: 21 | - export PATH=$PATH:$HOME/gopath/bin 22 | # - go get -u github.com/shirou/gopsutil 23 | - go get -v -t ./... 24 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution Guidelines 2 | 3 | ## Introduction 4 | 5 | This document explains how to contribute changes to the Ego project. It assumes you have followed the README.md and [API Document](https://github.com/vcaesar/tt/tree/master/docs). 6 | 7 | ## Bug reports 8 | 9 | Please search the issues on the issue tracker with a variety of keywords to ensure your bug is not already reported. 10 | 11 | If unique, [open an issue](https://github.com/vcaesar/tt/issues/new) and answer the questions so we can understand and reproduce the problematic behavior. 12 | 13 | The burden is on you to convince us that it is actually a bug in Ego. This is easiest to do when you write clear, concise instructions so we can reproduce the behavior (even if it seems obvious). The more detailed and specific you are, the faster we will be able to help you. Check out [How to Report Bugs Effectively](http://www.chiark.greenend.org.uk/~sgtatham/bugs.html). 14 | 15 | Please be kind, remember that Ego comes at no cost to you, and you're getting free help. 16 | 17 | ## Discuss your design 18 | 19 | The project welcomes submissions but please let everyone know what you're working on if you want to change or add something to the Ego repositories. 20 | 21 | Before starting to write something new for the Ego project, please [file an issue](https://github.com/vcaesar/tt/issues/new). Significant changes must go through the [change proposal process](https://github.com/go-ego/proposals) before they can be accepted. 22 | 23 | This process gives everyone a chance to validate the design, helps prevent duplication of effort, and ensures that the idea fits inside the goals for the project and tools. It also checks that the design is sound before code is written; the code review tool is not the place for high-level discussions. 24 | 25 | ## Testing redux 26 | 27 | Before sending code out for review, run all the tests for the whole tree to make sure the changes don't break other usage and keep the compatibility on upgrade. You must be test on Mac, Windows, Linux and other. You should install the CLI for Circle CI, as we are using the server for continous testing. 28 | 29 | ## Code review 30 | 31 | In addition to the owner, Changes to Ego must be reviewed before they are accepted, no matter who makes the change even if it is a maintainer. We use GitHub's pull request workflow to do that and we also use [LGTM](http://lgtm.co) to ensure every PR is reviewed by vz or least 2 maintainers. 32 | 33 | 34 | ## Sign your work 35 | 36 | The sign-off is a simple line at the end of the explanation for the patch. Your signature certifies that you wrote the patch or otherwise have the right to pass it on as an open-source patch. 37 | 38 | ## Maintainers 39 | 40 | To make sure every PR is checked, we got team maintainers. A maintainer should be a contributor of Ego and contributed at least 4 accepted PRs. 41 | 42 | ## Owners 43 | 44 | Since Ego is a pure community organization without any company support, Copyright 2016 The go-ego Project Developers. 45 | 46 | 47 | ## Versions 48 | 49 | Ego has the `master` branch as a tip branch and has version branches such as `v0.30.0`. `v0.40.0` is a release branch and we will tag `v0.40.0` for binary download. If `v0.40.0` has bugs, we will accept pull requests on the `v0.40.0` branch and publish a `v0.40.1` tag, after bringing the bug fix also to the master branch. 50 | 51 | Since the `master` branch is a tip version, if you wish to use Ego in production, please download the latest release tag version. All the branches will be protected via GitHub, all the PRs to every branch must be reviewed by two maintainers and must pass the automatic tests. 52 | 53 | ## Copyright 54 | 55 | Code that you contribute should use the standard copyright header: 56 | 57 | ``` 58 | // Copyright 2018 The go-ego Project Developers. 59 | // 60 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 61 | // not use this file except in compliance with the License. You may obtain 62 | // a copy of the License at 63 | // 64 | // http://www.apache.org/licenses/LICENSE-2.0 65 | // 66 | // Unless required by applicable law or agreed to in writing, software 67 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 68 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 69 | // License for the specific language governing permissions and limitations 70 | // under the License. 71 | ``` 72 | 73 | Files in the repository contain copyright from the year they are added to the year they are last changed. If the copyright author is changed, just paste the header below the old one. 74 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tt 2 | Simple and colorful test tools 3 | 4 | [![CircleCI Status](https://circleci.com/gh/vcaesar/tt.svg?style=shield)](https://circleci.com/gh/vcaesar/tt) 5 | ![Appveyor](https://ci.appveyor.com/api/projects/status/github/vcaesar/tt?branch=master&svg=true) 6 | [![codecov](https://codecov.io/gh/vcaesar/tt/branch/master/graph/badge.svg)](https://codecov.io/gh/vcaesar/tt) 7 | [![Build Status](https://travis-ci.org/vcaesar/tt.svg)](https://travis-ci.org/vcaesar/tt) 8 | [![Go Report Card](https://goreportcard.com/badge/github.com/vcaesar/tt)](https://goreportcard.com/report/github.com/vcaesar/tt) 9 | [![GoDoc](https://godoc.org/github.com/vcaesar/tt?status.svg)](https://godoc.org/github.com/vcaesar/tt) 10 | [![Release](https://github-release-version.herokuapp.com/github/vcaesar/tt/release.svg?style=flat)](https://github.com/vcaesar/tt/releases/latest) 11 | [![Join the chat at https://gitter.im/go-ego/ego](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/go-ego/ego?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 12 | 13 | ## Installation/Update 14 | 15 | ``` 16 | go get -u github.com/vcaesar/tt 17 | ``` 18 | 19 | ## Usage: 20 | 21 | #### [Look at an example](/example/) 22 | 23 | ```go 24 | package tt 25 | 26 | import ( 27 | "fmt" 28 | "testing" 29 | 30 | "github.com/vcaesar/tt" 31 | "github.com/vcaesar/tt/example" 32 | ) 33 | 34 | func TestAdd(t *testing.T) { 35 | fmt.Println(add.Add(1, 1)) 36 | 37 | tt.Expect(t, "1", add.Add(1, 1)) 38 | tt.Expect(t, "2", add.Add(1, 1)) 39 | 40 | tt.Equal(t, 1, add.Add(1, 1)) 41 | tt.Equal(t, 2, add.Add(1, 1)) 42 | 43 | at := tt.New(t) 44 | at.Expect("2", add.Add(1, 1)) 45 | at.Equal(2, add.Add(1, 1)) 46 | } 47 | 48 | func Benchmark1(b *testing.B) { 49 | at := tt.New(b) 50 | fn := func() { 51 | at.Equal(2, add.Add(1, 1)) 52 | } 53 | 54 | tt.BM(b, fn) 55 | // at.BM(b, fn) 56 | } 57 | 58 | func Benchmark2(b *testing.B) { 59 | at := tt.New(b) 60 | for i := 0; i < b.N; i++ { 61 | at.Equal(2, Add(1, 1)) 62 | } 63 | } 64 | 65 | ``` 66 | ## Thanks 67 | 68 | [Testify](https://github.com/stretchr/testify), the code has some inspiration. -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: "{build}" 2 | image: "Visual Studio 2017" 3 | # platform: x64 4 | 5 | clone_folder: c:\gopath\src\github.com\vcaesar\tt 6 | # max_jobs: 1 7 | 8 | environment: 9 | global: 10 | GOPATH: C:\gopath 11 | # CC: gcc.exe 12 | matrix: 13 | - GOARCH: amd64 14 | # - GOARCH: 386 15 | GOVERSION: 1.24.0 16 | # GOPATH: c:\gopath 17 | 18 | install: 19 | - set PATH=%GOPATH%\bin;c:\go\bin;%PATH% 20 | - git submodule update --init 21 | - rmdir C:\go /s /q 22 | - appveyor DownloadFile https://storage.googleapis.com/golang/go%GOVERSION%.windows-%GOARCH%.zip 23 | - 7z x go%GOVERSION%.windows-%GOARCH%.zip -y -oC:\ > NUL 24 | - go version 25 | - go env 26 | # - gcc --version 27 | 28 | # To run your custom scripts instead of automatic MSBuild 29 | build_script: 30 | # We need to disable firewall - https://github.com/appveyor/ci/issues/1579#issuecomment-309830648 31 | - ps: Disable-NetFirewallRule -DisplayName 'File and Printer Sharing (SMB-Out)' 32 | - cd c:\gopath\src\github.com\vcaesar\tt 33 | - git branch 34 | - go get -t ./... 35 | 36 | # To run your custom scripts instead of automatic tests 37 | test_script: 38 | # Unit tests 39 | - ps: Add-AppveyorTest "Unit Tests" -Outcome Running 40 | # - go test -u github.com/vcaesar/tt/... 41 | - go test -v github.com/vcaesar/tt/... 42 | - ps: Update-AppveyorTest "Unit Tests" -Outcome Passed 43 | -------------------------------------------------------------------------------- /assert.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The go-ego Project Developers. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package tt 16 | 17 | import ( 18 | "testing" 19 | ) 20 | 21 | // Assertions provides assertion methods around the 22 | // TestingT interface. 23 | type Assertions struct { 24 | t TestingT 25 | } 26 | 27 | // New makes a new Assertions object for the specified TestingT. 28 | func New(t TestingT) *Assertions { 29 | return &Assertions{ 30 | t: t, 31 | } 32 | } 33 | 34 | // BM is the encapsulation of the benchmark function 35 | // func Benchmark1(b *testing.B, fn func()) 36 | func (at *Assertions) BM(b *testing.B, fn func()) { 37 | for i := 0; i < b.N; i++ { 38 | fn() 39 | } 40 | } 41 | 42 | // IsType asserts that two objects type are equal 43 | func (at *Assertions) IsType(expect string, actual interface{}, args ...interface{}) bool { 44 | info, call, cinfo := typeCall(expect, actual, args...) 45 | return IsType(at.t, expect, actual, info, call+1, cinfo) 46 | } 47 | 48 | // Equal asserts that two objects are equal. 49 | func (at *Assertions) Equal(expect, actual interface{}, args ...interface{}) bool { 50 | info, call, cinfo := typeCall(expect, actual, args...) 51 | 52 | return Equal(at.t, expect, actual, info, call, cinfo) 53 | } 54 | 55 | // Expect asserts that string and objects are equal. 56 | func (at *Assertions) Expect(expect string, actual interface{}, args ...interface{}) bool { 57 | info, call, cinfo := argsFn(args...) 58 | return Expect(at.t, expect, actual, info, call, cinfo) 59 | } 60 | 61 | // Nil asserts that nil and objects are equal. 62 | func (at *Assertions) Nil(actual interface{}, args ...interface{}) bool { 63 | info, call, cinfo := typeCall(nil, actual, args...) 64 | return Equal(at.t, nil, actual, info, call, cinfo) 65 | } 66 | 67 | // NotNil asserts that not equal nil. 68 | // 69 | // at.NotNil(t *testing.T, 1) 70 | // 71 | func (at *Assertions) NotNil(actual interface{}, args ...interface{}) bool { 72 | info, call, cinfo := callAdd(Type, args...) 73 | return NotEqual(at.t, nil, actual, info, call, cinfo) 74 | } 75 | 76 | // Error asserts that not equal error. 77 | // 78 | // at.Error(t *testing.T, err) 79 | // 80 | func (at *Assertions) Error(actual interface{}, args ...interface{}) bool { 81 | info, call, cinfo := callAdd(Type, args...) 82 | return IsType(at.t, "*errors.errorString", actual, info, call, cinfo) 83 | } 84 | 85 | // Empty asserts that empty and objects are equal. 86 | func (at *Assertions) Empty(actual interface{}, args ...interface{}) bool { 87 | info, call, cinfo := typeCall("", actual, args...) 88 | return Equal(at.t, "", actual, info, call, cinfo) 89 | } 90 | 91 | // NotEmpty asserts that empty and objects are not equal. 92 | func (at Assertions) NotEmpty(actual interface{}, args ...interface{}) bool { 93 | info, call, cinfo := callAdd(Type, args...) 94 | return NotEqual(at.t, "", actual, info, call, cinfo) 95 | } 96 | 97 | // Zero asserts that zero and objects are equal. 98 | func (at *Assertions) Zero(actual interface{}, args ...interface{}) bool { 99 | info, call, cinfo := typeCall(0, actual, args...) 100 | return Equal(at.t, 0, actual, info, call, cinfo) 101 | } 102 | 103 | // NotZero asserts that zero and objects are not equal. 104 | func (at *Assertions) NotZero(actual interface{}, args ...interface{}) bool { 105 | info, call, cinfo := callAdd(Type, args...) 106 | return NotEqual(at.t, 0, actual, info, call, cinfo) 107 | } 108 | 109 | // Bool asserts that true and objects are equal. 110 | func (at *Assertions) Bool(actual interface{}, args ...interface{}) bool { 111 | info, call, cinfo := typeCall(true, actual, args...) 112 | return Equal(at.t, true, actual, info, call, cinfo) 113 | } 114 | 115 | // True asserts that true and objects are equal. 116 | func (at *Assertions) True(actual interface{}, args ...interface{}) bool { 117 | info, call, cinfo := typeCall(true, actual, args...) 118 | return Equal(at.t, true, actual, info, call, cinfo) 119 | } 120 | 121 | // False asserts that flase and objects are equal. 122 | func (at *Assertions) False(actual interface{}, args ...interface{}) bool { 123 | info, call, cinfo := typeCall(false, actual, args...) 124 | return Equal(at.t, false, actual, info, call, cinfo) 125 | } 126 | 127 | // Not asserts that two objects are not equal. 128 | func (at *Assertions) Not(expect, actual interface{}, args ...interface{}) bool { 129 | info, call, cinfo := callAdd(Type, args...) 130 | return NotEqual(at.t, expect, actual, info, call, cinfo) 131 | } 132 | 133 | // NotEqual asserts that two objects are not equal. 134 | func (at *Assertions) NotEqual(expect, actual interface{}, args ...interface{}) bool { 135 | info, call, cinfo := callAdd(Type, args...) 136 | return NotEqual(at.t, expect, actual, info, call, cinfo) 137 | } 138 | 139 | // NotExpect asserts that string and objects are not equal. 140 | func (at *Assertions) NotExpect(expect string, actual interface{}, args ...interface{}) bool { 141 | info, call, cinfo := argsFn(args...) 142 | return NotExpect(at.t, expect, actual, info, call, cinfo) 143 | } 144 | -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | # circle.yml # 2 | # machine: 3 | # go: 4 | # version: 1.9.1 5 | 6 | version: 2 7 | 8 | jobs: 9 | build: 10 | docker: 11 | - image: golang:1.24.0 12 | working_directory: /gopath/src/github.com/vcaesar/tt 13 | steps: 14 | - checkout 15 | # specify any bash command here prefixed with `run: ` 16 | - run: go get -v -t -d ./... 17 | - run: go test -v ./... 18 | # codecov.io 19 | - run: go test -v -covermode=count -coverprofile=coverage.out 20 | - run: bash <(curl -s https://codecov.io/bash) 21 | # script: 22 | # - ./go.test.sh 23 | -------------------------------------------------------------------------------- /cov.go: -------------------------------------------------------------------------------- 1 | package tt 2 | -------------------------------------------------------------------------------- /dbg.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The go-ego Project Developers. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package tt 16 | 17 | import ( 18 | "log" 19 | "strings" 20 | ) 21 | 22 | func fmtDbg(s string, v ...interface{}) (arr []interface{}) { 23 | info := "" 24 | if strings.Contains(s, "t: ") { 25 | info = RedBold("Trace:" + strings.TrimLeft(s, "t:") + ", ") 26 | } else { 27 | info = RedBold("Trace: " + CallerInfo()[3] + ", ") 28 | info += Blue(s) 29 | } 30 | 31 | arr = append(arr, info) 32 | arr = append(arr, v...) 33 | 34 | return 35 | } 36 | 37 | // Log dbg println log 38 | func Log(s string, v ...interface{}) error { 39 | arr := fmtDbg(s, v...) 40 | log.Println(arr...) 41 | return nil 42 | } 43 | 44 | // Err dbg fatal error log 45 | func Err(s string, v ...interface{}) error { 46 | err := fmtDbg(s, v...) 47 | log.Fatalln(err...) 48 | return nil 49 | } 50 | 51 | func apiCall(info ...string) string { 52 | call := "" 53 | if len(info) > 0 && info[0] != "" { 54 | call = RedBold("\n Error Trace: " + info[0] + ", ") 55 | } else { 56 | call = RedBold("\n Error Trace: " + CallerInfo()[3] + ", ") 57 | } 58 | 59 | return call 60 | } 61 | 62 | // Drop set drop tag and println log 63 | func Drop(api, use string, info ...string) bool { 64 | call := apiCall(info...) 65 | s := call + Yellow("Warning: "+Blue(api)+" is droped! Use "+Red(use)+".") 66 | log.Println(s) 67 | 68 | return true 69 | } 70 | 71 | // UnUsed not used tag and println log 72 | func UnUsed(v string, info ...string) bool { 73 | call := apiCall(info...) 74 | s := call + Yellow("Warning: "+Blue(v)+" is not used!") 75 | log.Println(s) 76 | 77 | return true 78 | } 79 | -------------------------------------------------------------------------------- /example/add.go: -------------------------------------------------------------------------------- 1 | package add 2 | 3 | // Add a add test func 4 | func Add(a, b int) int { 5 | return a + b 6 | } 7 | -------------------------------------------------------------------------------- /example/add_test.go: -------------------------------------------------------------------------------- 1 | package add 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/vcaesar/tt" 8 | ) 9 | 10 | func TestAdd(t *testing.T) { 11 | fmt.Println(Add(1, 1)) 12 | 13 | // tt.Expect(t, "1", Add(1, 1)) 14 | tt.Expect(t, "2", Add(1, 1)) 15 | // tt.Equal(t, 1, Add(1, 1)) 16 | tt.Equal(t, 2, Add(1, 1)) 17 | 18 | at := tt.New(t) 19 | at.Expect("2", Add(1, 1)) 20 | at.Equal(2, Add(1, 1)) 21 | } 22 | 23 | func Benchmark1(b *testing.B) { 24 | at := tt.New(b) 25 | fn := func() { 26 | at.Equal(2, Add(1, 1)) 27 | } 28 | 29 | tt.BM(b, fn) 30 | // at.BM(b, fn) 31 | } 32 | 33 | func Benchmark2(b *testing.B) { 34 | at := tt.New(b) 35 | for i := 0; i < b.N; i++ { 36 | at.Equal(2, Add(1, 1)) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /fn.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The go-ego Project Developers. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package tt 16 | 17 | import ( 18 | "fmt" 19 | "runtime" 20 | "strings" 21 | "unicode" 22 | "unicode/utf8" 23 | ) 24 | 25 | // Blue returns a blue string 26 | func Blue(message string) string { 27 | return fmt.Sprintf("\x1b[34m%s\x1b[0m", message) 28 | } 29 | 30 | // Red returns a red string 31 | func Red(message string) string { 32 | return fmt.Sprintf("\x1b[31m%s\x1b[0m", message) 33 | } 34 | 35 | // Yellow returns a yellow string 36 | func Yellow(message string) string { 37 | return fmt.Sprintf("\x1b[33m%s\x1b[0m", message) 38 | } 39 | 40 | // Bold returns a blod string 41 | func Bold(message string) string { 42 | return fmt.Sprintf("\x1b[1m%s\x1b[21m", message) 43 | } 44 | 45 | // RedBold returns a red bold string 46 | func RedBold(message string) string { 47 | return fmt.Sprintf("\x1b[31m%s\x1b[0m", Bold(message)) 48 | } 49 | 50 | func isTest(name, prefix string) bool { 51 | if !strings.HasPrefix(name, prefix) { 52 | return false 53 | } 54 | if len(name) == len(prefix) { // "Test" is ok 55 | return true 56 | } 57 | rune, _ := utf8.DecodeRuneInString(name[len(prefix):]) 58 | return !unicode.IsLower(rune) 59 | } 60 | 61 | // CallerInfo returns an array of strings containing the file and line number, 62 | // and each stack frame leading from the current test, when the assert call that 63 | // failed. 64 | func CallerInfo() (callers []string) { 65 | var ( 66 | pc uintptr 67 | file, name string 68 | line int 69 | ok bool 70 | ) 71 | 72 | for i := 0; ; i++ { 73 | pc, file, line, ok = runtime.Caller(i) 74 | if !ok { 75 | // The breaks below failed to terminate the loop, and we ran off the 76 | // end of the call stack. 77 | break 78 | } 79 | 80 | // This is a huge edge case, but it will panic if this is the case, see #180 81 | if file == "" { 82 | break 83 | } 84 | 85 | f := runtime.FuncForPC(pc) 86 | if f == nil { 87 | break 88 | } 89 | name = f.Name() 90 | 91 | // testing.tRunner is the standard library function that calls 92 | // tests. 93 | if name == "testing.tRunner" { 94 | break 95 | } 96 | 97 | parts := strings.Split(file, "/") 98 | file = parts[len(parts)-1] 99 | if len(parts) > 1 { 100 | dir := parts[len(parts)-2] 101 | if (dir != "assert" && dir != "mock" && dir != "require") || 102 | file == "mock_test.go" { 103 | callers = append(callers, fmt.Sprintf("%s:%d", file, line)) 104 | } 105 | } 106 | 107 | // Drop the package 108 | segments := strings.Split(name, ".") 109 | name = segments[len(segments)-1] 110 | if isTest(name, "Test") || 111 | isTest(name, "Benchmark") || 112 | isTest(name, "Example") { 113 | break 114 | } 115 | } 116 | 117 | return 118 | } 119 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/vcaesar/tt 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /http.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The go-ego Project Developers. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package tt 16 | -------------------------------------------------------------------------------- /http/http.go: -------------------------------------------------------------------------------- 1 | package http 2 | -------------------------------------------------------------------------------- /mock/mock.go: -------------------------------------------------------------------------------- 1 | package mock 2 | -------------------------------------------------------------------------------- /sql.go: -------------------------------------------------------------------------------- 1 | package tt 2 | -------------------------------------------------------------------------------- /tt.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The go-ego Project Developers. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | // package tt is simple and colorful test tools 16 | 17 | package tt 18 | 19 | import ( 20 | "fmt" 21 | "log" 22 | "reflect" 23 | "testing" 24 | "time" 25 | 26 | "net/http" 27 | // _ "net/http/pprof" 28 | ) 29 | 30 | const ( 31 | // Version get the tt version 32 | Version = "v0.20.0.77, Sierra Nevada!" 33 | ) 34 | 35 | var ( 36 | // Type type must 37 | Type bool 38 | ) 39 | 40 | // Pprof use: 41 | // Mem: 42 | // pprof -http=:8090 http://127.0.0.1:6060/debug/pprof/heap 43 | // 44 | // go tool pprof http://localhost:6060/debug/pprof/heap 45 | // 46 | // CPU: 47 | // debug/pprof/profile 48 | // set time: 49 | // debug/pprof/profile\?seconds\=10 50 | // pprof -http=:8090 http://127.0.0.1:6060/debug/pprof/profile\?seconds\=10 51 | // 52 | // debug/pprof/block 53 | // debug/pprof/mutex 54 | func Pprof(tm ...int) bool { 55 | go func() { 56 | log.Println(http.ListenAndServe("127.0.0.1:6060", nil)) 57 | }() 58 | 59 | if len(tm) > 0 { 60 | time.Sleep(time.Duration(tm[0]) * time.Second) 61 | } 62 | 63 | return true 64 | } 65 | 66 | // TestingT is an interface wrapper around *testing.T 67 | type TestingT interface { 68 | Errorf(format string, args ...interface{}) 69 | } 70 | 71 | // BM func Benchmark1(b *testing.B, fn func()) 72 | func BM(b *testing.B, fn func()) { 73 | for i := 0; i < b.N; i++ { 74 | fn() 75 | } 76 | } 77 | 78 | func typeMap(expect string) string { 79 | m := map[string]string{ 80 | "str": "string", 81 | "int": "int", 82 | "i8": "int8", 83 | "i16": "int16", 84 | "i32": "int32", 85 | "i64": "int64", 86 | "u": "uint", 87 | "u8": "uint8", 88 | "u16": "uint16", 89 | "ui32": "uint32", 90 | "ui64": "uint64", 91 | "f32": "float32", 92 | "f64": "float64", 93 | "b": "bool", 94 | "m": "map", 95 | "ch": "chan", 96 | "stu": "struct", 97 | "bytes": "[]byte", 98 | "u8s": "[]uint8", 99 | "c64": "complex64", 100 | "c128": "complex128", 101 | } 102 | 103 | return m[expect] 104 | } 105 | 106 | // IsTypes return bool when actual is expect type 107 | func IsTypes(expect string, actual interface{}) bool { 108 | mt := typeMap(expect) 109 | s := reflect.TypeOf(actual).String() 110 | if s == mt || s == expect { 111 | return true 112 | } 113 | 114 | return false 115 | } 116 | 117 | func typVal(expect string) string { 118 | ept := typeMap(expect) 119 | if ept == "" { 120 | ept = expect 121 | } 122 | 123 | return ept 124 | } 125 | 126 | // TypeOf equal two interface{} type 127 | func TypeOf(expect, actual interface{}) bool { 128 | return reflect.TypeOf(expect) == reflect.TypeOf(actual) 129 | } 130 | 131 | // IsType asserts that two objects type are equal 132 | func IsType(t TestingT, expect string, actual interface{}, args ...interface{}) bool { 133 | if actual == nil && expect == "nil" { 134 | return true 135 | } 136 | if actual == nil { 137 | return false 138 | } 139 | 140 | s := reflect.TypeOf(actual).String() 141 | expect = typVal(expect) 142 | 143 | info, call, cinfo := typeCall(expect, s, args...) 144 | return Equal(t, expect, s, info, call, cinfo) 145 | } 146 | 147 | // TypeF make Type false 148 | func TypeF() { 149 | Type = false 150 | } 151 | 152 | func argsFn(args ...interface{}) (string, int, string) { 153 | info := "" 154 | if len(args) > 0 { 155 | info = args[0].(string) 156 | } 157 | 158 | call := 5 159 | callInfo := "" 160 | if len(args) > 1 { 161 | if TypeOf(args[1], callInfo) { 162 | callInfo = args[1].(string) 163 | return info, call, callInfo 164 | } 165 | 166 | call = args[1].(int) 167 | } 168 | 169 | return info, call, callInfo 170 | } 171 | 172 | func callSub(args ...interface{}) (string, int, string) { 173 | info, call, cinfo := argsFn(args...) 174 | if len(args) < 1 { 175 | call = call - 1 176 | } 177 | return info, call, cinfo 178 | } 179 | 180 | func callAdd(t bool, args ...interface{}) (string, int, string) { 181 | info, call, cinfo := argsFn(args...) 182 | if len(args) < 1 && !t { 183 | call = call + 1 184 | } 185 | 186 | return info, call, cinfo 187 | } 188 | 189 | func typeCall(expect, actual interface{}, args ...interface{}) (string, int, string) { 190 | b := Type && !TypeOf(expect, actual) 191 | return callAdd(b, args...) 192 | } 193 | 194 | // Fmt return error string 195 | func Fmt(equal, expect string, call int, info ...string) (err string) { 196 | if len(info) > 1 && info[1] != "" { 197 | err = RedBold("\n Error Trace: " + info[1] + ",") 198 | } else { 199 | err = RedBold("\n Error Trace: " + CallerInfo()[call] + ",") 200 | } 201 | 202 | err += Yellow("\n Error: " + equal + "; \n ") 203 | if len(info) > 0 && info[0] != "" { 204 | err += "Messages: " + info[0] + "\n " 205 | } 206 | 207 | err += Blue(expect+": '%s',\n ") + Red("but got: '%s' \n\n") 208 | return 209 | } 210 | 211 | // FmtErr return error string 212 | func FmtErr(call int, info ...string) string { 213 | return Fmt("Not Equal", "expected", call, info...) 214 | } 215 | 216 | // DEqual asserts that two objects are deep equal. 217 | // 218 | // tt.DEqual(t *testing.T, 1, 1) 219 | // 220 | func DEqual(t TestingT, expect, actual interface{}, args ...interface{}) bool { 221 | info, call, cinfo := argsFn(args...) 222 | Type = true 223 | defer TypeF() 224 | 225 | if TypeOf(expect, actual) { 226 | call = call + 1 227 | } 228 | 229 | return Equal(t, expect, actual, info, call, cinfo) 230 | } 231 | 232 | // Equal asserts that two objects are equal. 233 | // 234 | // tt.Equal(t *testing.T, 1, 1) 235 | // 236 | func Equal(t TestingT, expect, actual interface{}, args ...interface{}) bool { 237 | info, call, cinfo := argsFn(args...) 238 | if len(args) > 2 { 239 | cinfo = args[2].(string) 240 | } 241 | 242 | if Type && !TypeOf(expect, actual) { 243 | if len(args) < 2 { 244 | call = call - 1 245 | } 246 | 247 | err := FmtErr(call, info, cinfo) 248 | t.Errorf(err, expect, actual) 249 | return false 250 | } 251 | 252 | expectStr := fmt.Sprint(expect) 253 | return Expect(t, expectStr, actual, info, call, cinfo) 254 | } 255 | 256 | // Expect asserts that string and objects are equal. 257 | // 258 | // tt.Expect(t *testing.T, "1", 1) 259 | // 260 | func Expect(t TestingT, expect string, actual interface{}, args ...interface{}) bool { 261 | info, call, cinfo := callSub(args...) 262 | if len(args) > 2 { 263 | cinfo = args[2].(string) 264 | } 265 | 266 | actualStr := fmt.Sprint(actual) 267 | if expect != actualStr { 268 | err := FmtErr(call, info, cinfo) 269 | 270 | t.Errorf(err, expect, actualStr) 271 | return false 272 | } 273 | 274 | return true 275 | } 276 | 277 | // Nil asserts that nil and objects are equal. 278 | func Nil(t TestingT, actual interface{}, args ...interface{}) bool { 279 | info, call, cinfo := typeCall(nil, actual, args...) 280 | return Equal(t, nil, actual, info, call, cinfo) 281 | } 282 | 283 | // NotNil asserts that not equal nil. 284 | // 285 | // tt.NotNil(t *testing.T, 1) 286 | // 287 | func NotNil(t TestingT, actual interface{}, args ...interface{}) bool { 288 | info, call, cinfo := callAdd(Type, args...) 289 | return NotEqual(t, nil, actual, info, call, cinfo) 290 | } 291 | 292 | // Error asserts that equal error. 293 | func Error(t TestingT, actual interface{}, args ...interface{}) bool { 294 | info, call, cinfo := callAdd(Type, args...) 295 | return IsType(t, "*errors.errorString", actual, info, call, cinfo) 296 | } 297 | 298 | // Empty asserts that empty and objects are equal. 299 | func Empty(t TestingT, actual interface{}, args ...interface{}) bool { 300 | info, call, cinfo := typeCall("", actual, args...) 301 | return Equal(t, "", actual, info, call, cinfo) 302 | } 303 | 304 | // NotEmpty asserts that empty and objects are not equal. 305 | func NotEmpty(t TestingT, actual interface{}, args ...interface{}) bool { 306 | info, call, cinfo := callAdd(Type, args...) 307 | return NotEqual(t, "", actual, info, call, cinfo) 308 | } 309 | 310 | // Zero asserts that zero and objects are equal. 311 | func Zero(t TestingT, actual interface{}, args ...interface{}) bool { 312 | info, call, cinfo := typeCall(0, actual, args...) 313 | return Equal(t, 0, actual, info, call, cinfo) 314 | } 315 | 316 | // NotZero asserts that zero and objects are not equal. 317 | func NotZero(t TestingT, actual interface{}, args ...interface{}) bool { 318 | info, call, cinfo := callAdd(Type, args...) 319 | return NotEqual(t, 0, actual, info, call, cinfo) 320 | } 321 | 322 | // Bool asserts that true and objects are equal. 323 | func Bool(t TestingT, actual interface{}, args ...interface{}) bool { 324 | info, call, cinfo := typeCall(true, actual, args...) 325 | 326 | return Equal(t, true, actual, info, call, cinfo) 327 | } 328 | 329 | // True asserts that true and objects are equal. 330 | func True(t TestingT, actual interface{}, args ...interface{}) bool { 331 | info, call, cinfo := typeCall(true, actual, args...) 332 | 333 | return Equal(t, true, actual, info, call, cinfo) 334 | } 335 | 336 | // False asserts that flase and objects are equal. 337 | func False(t TestingT, actual interface{}, args ...interface{}) bool { 338 | info, call, cinfo := typeCall(false, actual, args...) 339 | 340 | return Equal(t, false, actual, info, call, cinfo) 341 | } 342 | 343 | // NotErr return not equal error string 344 | func NotErr(call int, info ...string) string { 345 | return Fmt("Equal", "not expected", call, info...) 346 | } 347 | 348 | // Not asserts that two objects are not equal. 349 | // 350 | // tt.NotEqual(t *testing.T, 1, 1) 351 | // 352 | func Not(t TestingT, expect, actual interface{}, args ...interface{}) bool { 353 | info, call, cinfo := callAdd(Type, args...) 354 | 355 | return NotEqual(t, expect, actual, info, call, cinfo) 356 | } 357 | 358 | // NotEqual asserts that two objects are not equal. 359 | // 360 | // tt.NotEqual(t *testing.T, 1, 1) 361 | // 362 | func NotEqual(t TestingT, expect, actual interface{}, args ...interface{}) bool { 363 | info, call, cinfo := argsFn(args...) 364 | if len(args) > 2 { 365 | cinfo = args[2].(string) 366 | } 367 | 368 | if Type && TypeOf(expect, actual) { 369 | if len(args) < 2 { 370 | call = call - 1 371 | } 372 | 373 | err := NotErr(call, info, cinfo) 374 | t.Errorf(err, expect, actual) 375 | return false 376 | } 377 | 378 | if Type && !TypeOf(expect, actual) { 379 | return true 380 | } 381 | 382 | expectStr := fmt.Sprint(expect) 383 | return NotExpect(t, expectStr, actual, info, call, cinfo) 384 | } 385 | 386 | // NotExpect asserts that string and objects are not equal. 387 | // 388 | // tt.NotExpect(t *testing.T, "1", 1) 389 | // 390 | func NotExpect(t TestingT, expect string, actual interface{}, args ...interface{}) bool { 391 | info, call, cinfo := callSub(args...) 392 | if len(args) > 2 { 393 | cinfo = args[2].(string) 394 | } 395 | 396 | actualStr := fmt.Sprint(actual) 397 | if expect == actualStr { 398 | err := NotErr(call, info, cinfo) 399 | 400 | t.Errorf(err, expect, actualStr) 401 | return false 402 | } 403 | 404 | return true 405 | } 406 | -------------------------------------------------------------------------------- /tt_test.go: -------------------------------------------------------------------------------- 1 | package tt 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "testing" 7 | 8 | add "github.com/vcaesar/tt/example" 9 | ) 10 | 11 | func TestTT(t *testing.T) { 12 | mockT := new(testing.T) 13 | fmt.Println(Expect(mockT, "1", add.Add(1, 1))) 14 | 15 | if Expect(mockT, "1", add.Add(1, 1)) { 16 | t.Error("Equal should return false") 17 | } 18 | if Equal(mockT, "1", add.Add(1, 1)) { 19 | t.Error("Equal should return false") 20 | } 21 | 22 | if !Expect(mockT, "Hello World", "Hello World") { 23 | t.Error("Equal should return true") 24 | } 25 | if !Equal(mockT, "Hello World", "Hello World") { 26 | t.Error("Equal should return true") 27 | } 28 | 29 | fmt.Println(add.Add(1, 1)) 30 | 31 | // Expect(t, "1", add.Add(1, 1)) 32 | Expect(t, "2", add.Add(1, 1)) 33 | // Equal(t, 1, add.Add(1, 1)) 34 | Equal(t, 2, add.Add(1, 1)) 35 | 36 | Nil(t, nil) 37 | Error(t, errors.New("error new")) 38 | IsType(t, "nil", nil) 39 | Empty(t, "") 40 | Zero(t, 0) 41 | Bool(t, 1 == 1) 42 | True(t, 1 == 1) 43 | False(t, 1 != 1) 44 | 45 | at := New(t) 46 | at.Expect("2", add.Add(1, 1)) 47 | at.Equal(2, add.Add(1, 1)) 48 | 49 | at.Nil(nil) 50 | at.Empty("") 51 | at.Zero(0) 52 | at.Bool(1 == 1) 53 | at.True(1 == 1) 54 | at.False(1 != 1) 55 | 56 | True(t, Pprof(1)) 57 | } 58 | 59 | func TestNot(t *testing.T) { 60 | mockT := new(testing.T) 61 | fmt.Println(Expect(mockT, "1", add.Add(1, 1))) 62 | 63 | if !Not(mockT, "1", add.Add(1, 1)) { 64 | t.Error("Equal should return false") 65 | } 66 | if !NotExpect(mockT, "1", add.Add(1, 1)) { 67 | t.Error("Equal should return false") 68 | } 69 | if !NotEqual(mockT, "1", add.Add(1, 1)) { 70 | t.Error("Equal should return false") 71 | } 72 | 73 | if Not(mockT, "Hello World", "Hello World") { 74 | t.Error("Equal should return true") 75 | } 76 | if NotExpect(mockT, "Hello World", "Hello World") { 77 | t.Error("Equal should return true") 78 | } 79 | if NotEqual(mockT, "Hello World", "Hello World") { 80 | t.Error("Equal should return true") 81 | } 82 | 83 | fmt.Println(add.Add(1, 1)) 84 | 85 | Not(t, "3", add.Add(1, 1)) 86 | NotExpect(t, "3", add.Add(1, 1)) 87 | NotEqual(t, 3, add.Add(1, 1)) 88 | // 89 | NotNil(t, "nil", "", "tt_test.go:86") 90 | NotEmpty(t, 1) 91 | NotZero(t, "1") 92 | 93 | at := New(t) 94 | at.Not("3", add.Add(1, 1)) 95 | at.NotExpect("3", add.Add(1, 1)) 96 | at.NotEqual(3, add.Add(1, 1)) 97 | // 98 | at.NotNil("nil", "", "tt_test.go:95") 99 | at.NotEmpty(1) 100 | at.NotZero("1") 101 | } 102 | 103 | func TestArgs(t *testing.T) { 104 | Expect(t, "2", add.Add(1, 1), "must be expect", 3) 105 | Equal(t, 2, add.Add(1, 1), "", 4) 106 | 107 | NotExpect(t, "3", add.Add(1, 1), "", 3) 108 | Not(t, 3, add.Add(1, 1), "", 4) 109 | NotEqual(t, 3, add.Add(1, 1), "", 4) 110 | 111 | Nil(t, nil, "", 3) 112 | Empty(t, "", "", 3) 113 | Bool(t, 1 == 1, "", 4) 114 | True(t, 1 == 1, "", 4) 115 | False(t, 1 != 1, "", 4) 116 | IsType(t, "int", 11, "", 4) 117 | 118 | at := New(t) 119 | at.Expect("2", add.Add(1, 1), "", 4) 120 | at.Equal(2, add.Add(1, 1), "", 5) 121 | 122 | at.NotExpect("3", add.Add(1, 1), "", 4) 123 | at.Not("3", add.Add(1, 1), "", 5) 124 | at.NotEqual(3, add.Add(1, 1), "", 5) 125 | 126 | at.Nil(nil, "", 4) 127 | at.NotNil(1, "", "tt_test.go:127") 128 | at.Error(errors.New("error new"), "", "tt_test.go:128") 129 | at.Empty("", "", 4) 130 | at.Bool(1 == 1, "", 4) 131 | at.True(1 == 1, "", 4) 132 | at.False(1 != 1, "", 4) 133 | at.IsType("int", 11, "", 4) 134 | at.IsType("nil", nil) 135 | } 136 | 137 | func TestType(t *testing.T) { 138 | IsType(t, "int", 11) 139 | IsType(t, "f64", 0.1) 140 | IsTypes("f64", 0.1) 141 | 142 | Type = true 143 | Equal(t, 1, 1) 144 | Nil(t, nil) 145 | 146 | mockT := new(testing.T) 147 | if Equal(mockT, 1, "1", "must be equal", "tt/tt_test.go:125") { 148 | t.Error("Equal should return false") 149 | } 150 | 151 | if NotEqual(mockT, 1, 1, "must be not equal") { 152 | t.Error("Equal should return false") 153 | } 154 | 155 | if !NotEqual(mockT, 1, "1") { 156 | t.Error("Equal should return true") 157 | } 158 | 159 | DEqual(t, 1, 1, "", "tt/tt_test.go:137") 160 | } 161 | 162 | func TestDbg(t *testing.T) { 163 | Nil(t, Log("log test")) 164 | Nil(t, Log("t: tt/tt_test.go:156", "log test")) 165 | // Nil(t, Err("err test")) 166 | 167 | Bool(t, Drop("drop()", "new()")) 168 | Bool(t, Drop("drop()", "new()", "tt/tt_test.go:159")) 169 | Bool(t, UnUsed("v", "tt/tt_test.go:161")) 170 | } 171 | 172 | func Benchmark1(b *testing.B) { 173 | at := New(b) 174 | at.Bool(true) 175 | for i := 0; i < b.N; i++ { 176 | // do something 177 | // fmt.Println("do something") 178 | at.Equal(2, add.Add(1, 1)) 179 | } 180 | } 181 | 182 | func Benchmark2(b *testing.B) { 183 | fn := func() { 184 | Equal(b, 2, add.Add(1, 1)) 185 | } 186 | 187 | BM(b, fn) 188 | } 189 | 190 | func Benchmark3(b *testing.B) { 191 | at := New(b) 192 | fn := func() { 193 | at.Equal(2, add.Add(1, 1)) 194 | } 195 | 196 | at.BM(b, fn) 197 | } 198 | --------------------------------------------------------------------------------