h2non / baloo Goto Github PK
View Code? Open in Web Editor NEWExpressive end-to-end HTTP API testing made easy in Go
Home Page: https://godoc.org/github.com/h2non/baloo
License: MIT License
Expressive end-to-end HTTP API testing made easy in Go
Home Page: https://godoc.org/github.com/h2non/baloo
License: MIT License
Is there a way to get Baloo to ignore SSL certificate errors. I'm using a self-signed SSL certificate and my tests are generating errors like:
FAIL: TestUsers_List/Not_authenticated (0.35s)
expect.go:192: request error: Get https://core.myapp.test/v1/users: x509: certificate signed by unknown authority
FAIL: TestUsers_List/Authenticated_but_not_admin (0.11s)
expect.go:192: request error: Get https://core.myapp.test/v1/users: x509: certificate signed by unknown authority
When making HTTP requests in Go, it's possible to ignore SSL errors by configuring the Transport property like so:
tr := http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
}
client := http.Client{}
client.Transport = &tr
But where would I do this in baloo?
I have several test cases that perform JSON asserations. However, I need to extract specific fields from a JSON response that will be used for subsequent business logic.
How does one extract values from the response body?
An issue that has been bothering me for a while is that when a status assertion (it can be other assertion as well) fails, the response is not printed. Most of the time (at the least in the case of Rest APIs), the response contains a hint about why the status assertion fails, and it makes it easy to debug when the response is printed. Currently, I need to add parse and print response code everytime I need it, and it gets more annoying when tests are running in the CI. I am aware of the plugin https://github.com/izumin5210/gentleman-logger, but with the plugin the response is printed in all cases (and also it seems very old and not maintained). Example:
func TestXxx(t *testing.T) {
baloo.New("https://httpbin.org").Post("/anything").BodyString(`{"error":"db connection failed"}`).
Expect(t).Status(500).Done()
}
The assertion error in this case is Unexpected status code for: POST https://httpbin.org/anything => 200 != 500
To be able to see the error, one has to add some boilerplate code:
func TestXxx(t *testing.T) {
resp, _ := baloo.New("https://httpbin.org").Post("/anything").BodyString(`{"error":"db connection failed"}`).
Expect(t).Status(500).Send()
fmt.Println(resp.String())
}
It would be nice if this is provided out of the box, and only when the assertion fails.
When I provide:
t.Post("/v1/identifiers/druids").
SetHeader("Transfer-Encoding", "identity").
Expect(t).
Status(200).
Type("json").
JSON(map[string]string{"status": "OK"}).
Done()
When I look at the packets (via wireshark) I see that my header has been overwritten by: Transfer-Encoding: chunked
The following example doesn't work for me. In particular the expected json is null. Also httpbin now uses nginx instead of apache.
package simple
import (
"testing"
"gopkg.in/h2non/baloo.v1"
)
// test stores the HTTP testing client preconfigured
var test = baloo.New("http://httpbin.org")
func TestBalooSimple(t *testing.T) {
test.Get("/get").
SetHeader("Foo", "Bar").
Expect(t).
Status(200).
Header("Server", "apache").
Type("json").
JSON(map[string]string{"bar": "foo"}).
Done()
}
// assert implements an assertion function with custom validation logic.
// If the assertion fails it should return an error.
func assert(res *http.Response, req *http.Request) error {
if res.StatusCode >= 400 {
return errors.New("Invalid server response (> 400)")
}
return nil
}
func TestBalooClient(t *testing.T) {
baloo.AddAssertFunc('response.headers', assert)
test.Post("/post").
SetHeader("Foo", "Bar").
JSON(map[string]string{"foo": "bar"}).
Expect(t).
Status(200).
Type("json").
Assert('response.headers').
Done()
}
The following request as a Get or Post will always return a 308 if I do not set the Body as nil.
SetHeader("Authorization", bearerGithubToken()).
Body(nil).
Expect(t).
Status(200).
Done()```
On a Post I always get a 308.
``baseURL.Post("/v1/definition/stack").
SetHeader("Authorization", bearerGithubToken()).
JSON(app).
Expect(t).
Status(200).
Done()```
Each of these requests works correctly outside the baloo libraries. I have compared the request struct and cannot figure out the difference.
Any suggestions?
I'm trying to test Baloo to test my project's functionality. It works fine, but when running code coverage like so;
go test -v -covermode=atomic -coverprofile=coverage.out -run TestBalooSimple
I get coverage: 0.0% of statements
.
Maybe I'm doing it wrong with the command? Or is it running separately and won't work like this? Shouldn't coverage see that while the server is running (in the same code), that the Baloo-visits are actually hitting/covering code?
baloo.New("http://test").Get("/foo").Expect(t).Cookie("Foo", "bar")
Hi,
I was wondering: do you have a particular reason for having assert.unmarshalBody()
return map[string]interface{}
? Of course usually you deal with JSON objects, but JSON has many valid values (http://www.json.org):
null
I noticed this restriction because I ran into problems with assert a body using map[string]string
(which doesn't work, because assert.compare
assumes map[string]interface{}
is passed in the assertion. I can imagine that this is too strict and can be relaxed? E.g., checking if the value is a slice, struct, map, or implements json.Marshaler
? For example, gentleman uses the following logic:
// var data interface{}
switch data.(type) {
case string:
buf.WriteString(data.(string))
case []byte:
buf.Write(data.([]byte))
default:
if err := json.NewEncoder(buf).Encode(data); err != nil {
h.Error(ctx, err)
return
}
}
Would you accept a PR for this?
WARNING: DATA RACE
Write at 0x00c42035d090 by goroutine 44:
github.com/stratexio/wapi/vendor/gopkg.in/h2non/baloo.v0/assert.readBody()
/home/ubuntu/.go_workspace/src/github.com/stratexio/wapi/vendor/gopkg.in/h2non/baloo.v0/assert/body.go:18 +0x250
github.com/stratexio/wapi/vendor/gopkg.in/h2non/baloo.v0/assert.BodyMatchString.func1()
/home/ubuntu/.go_workspace/src/github.com/stratexio/wapi/vendor/gopkg.in/h2non/baloo.v0/assert/body.go:26 +0x6c
github.com/stratexio/wapi/vendor/gopkg.in/h2non/baloo%2ev0.(*Expect).run()
/home/ubuntu/.go_workspace/src/github.com/stratexio/wapi/vendor/gopkg.in/h2non/baloo.v0/expect.go:213 +0x93
github.com/stratexio/wapi/vendor/gopkg.in/h2non/baloo%2ev0.(*Expect).Done()
/home/ubuntu/.go_workspace/src/github.com/stratexio/wapi/vendor/gopkg.in/h2non/baloo.v0/expect.go:197 +0x257
github.com/stratexio/wapi/pkg/api/tokens_test.TestCreate.func1.2.2()
/home/ubuntu/.go_workspace/src/github.com/stratexio/wapi/pkg/api/tokens/create_test.go:169 +0xfe5
github.com/stratexio/wapi/vendor/github.com/franela/goblin.runIt.func1()
/home/ubuntu/.go_workspace/src/github.com/stratexio/wapi/vendor/github.com/franela/goblin/goblin.go:191 +0x34
Previous read at 0x00c42035d090 by goroutine 5:
github.com/stratexio/wapi/vendor/gopkg.in/h2non/gentleman%2ev1.EnsureResponseFinalized.func1()
/home/ubuntu/.go_workspace/src/github.com/stratexio/wapi/vendor/gopkg.in/h2non/gentleman.v1/response.go:232 +0x6d
Goroutine 44 (running) created at:
github.com/stratexio/wapi/vendor/github.com/franela/goblin.runIt()
/home/ubuntu/.go_workspace/src/github.com/stratexio/wapi/vendor/github.com/franela/goblin/goblin.go:191 +0x277
github.com/stratexio/wapi/vendor/github.com/franela/goblin.(*It).run()
/home/ubuntu/.go_workspace/src/github.com/stratexio/wapi/vendor/github.com/franela/goblin/goblin.go:128 +0xdf
github.com/stratexio/wapi/vendor/github.com/franela/goblin.(*Describe).run()
/home/ubuntu/.go_workspace/src/github.com/stratexio/wapi/vendor/github.com/franela/goblin/goblin.go:88 +0x18b
github.com/stratexio/wapi/vendor/github.com/franela/goblin.(*Describe).run()
/home/ubuntu/.go_workspace/src/github.com/stratexio/wapi/vendor/github.com/franela/goblin/goblin.go:88 +0x18b
github.com/stratexio/wapi/vendor/github.com/franela/goblin.(*G).Describe()
/home/ubuntu/.go_workspace/src/github.com/stratexio/wapi/vendor/github.com/franela/goblin/goblin.go:34 +0x2b9
github.com/stratexio/wapi/pkg/api/tokens_test.TestCreate()
/home/ubuntu/.go_workspace/src/github.com/stratexio/wapi/pkg/api/tokens/create_test.go:205 +0x180
testing.tRunner()
/usr/local/go/src/testing/testing.go:610 +0xc9
Goroutine 5 (running) created at:
runtime.createfing()
/usr/local/go/src/runtime/mfinal.go:139 +0x72
os.init()
/usr/local/go/src/os/file.go:54 +0x399
main.init()
github.com/stratexio/wapi/pkg/api/tokens/_test/_testmain.go:120 +0x9d
==================```
Not sure what to do with it :/ I'd rather not switch away from your library.
Hi!
A few days ago, I started using the Go linter (with Go 1.21). When running it on my Baloo tests, there were many warnings about ignoring the error returned by the Done()
method.
Even when looking at the first example below:
package simple
import (
"testing"
"gopkg.in/h2non/baloo.v3"
)
// test stores the HTTP testing client preconfigured
var test = baloo.New("http://httpbin.org")
func TestBalooSimple(t *testing.T) {
test.Get("/get").
SetHeader("Foo", "Bar").
Expect(t).
Status(200).
Header("Server", "apache").
Type("json").
JSON(map[string]string{"bar": "foo"}).
Done() // Warning: Error return value of `(gopkg.in/h2non/baloo.v3.Expect).Done` is not checked (errcheck)
}
Is there a good way to use Baloo without having the warning? One possibility would be to write this:
package simple
import (
"testing"
"gopkg.in/h2non/baloo.v3"
)
// test stores the HTTP testing client preconfigured
var test = baloo.New("http://httpbin.org")
func TestBalooSimple(t *testing.T) {
err := test.Get("/get").
SetHeader("Foo", "Bar").
Expect(t).
Status(200).
Header("Server", "apache").
Type("json").
JSON(map[string]string{"bar": "foo"}).
Done()
if err != nil {
t.Error(err)
}
}
But then the error is reported twice and it makes writing tests less friendly/readable.
It seems that the best way to handle this would be to remove the returned error from the Done()
method signature, or to provide another method that does not return the error.
Any thought? @h2non: I am willing to write a pull request if you agree with one of my propositions or if you have another one.
Currently only support Go's native testing
package. Alternative test runners could be supported as sort of adapters.
Listing a few for future consideration:
Very nice library! But there is one drawback.
Run this test
package baloo
import (
"gopkg.in/h2non/baloo.v3"
"testing"
)
func Test(t *testing.T) {
b := baloo.New("http://www.ya.ru")
_ = b.Get(".").Expect(t).Status(11).Done()
_ = b.Get(".").Expect(t).Status(11).Done()
_ = b.Get(".").Expect(t).Status(11).Done()
}
Look result
=== RUN Test
--- FAIL: Test (0.35s)
expect.go:204: Unexpected status code: 404 != 11
expect.go:204: Unexpected status code: 404 != 11
expect.go:204: Unexpected status code: 404 != 11
FAIL
Process finished with exit code 1
There is no way to know exactly where the test failed. The error message point inside the library
In the following code snippet the .JSON function changes the GET request to a POST request.
I found this very confusing, is this expected?
var test = baloo.New("http://httpbin.org")
func TestBalooClient(t *testing.T) {
test.Get("/get").
JSON(map[string]string{"foo": "bar"}).
Expect(t).
Status(200).
Type("json").
Done()
}
Hello,
when trying to validate the JSON object returned baloo
will fail if a string contains a newline. For example:
func TestATest(t *testing.T) {
testURL.
Post("/api/v1/endpoint/").
Expect(t).
Status(500).
Type("json").
JSON("{}").
Done()
}
Will break with the following error:
--- FAIL: TestATest (0.02s)
expect.go:199: failed to Unmarshal: invalid character '\n' in string literal
FAIL
If the JSON blob returned is:
{"a_valid_string": "asdadasd\nasdasdasdasd"}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.