Repository: labstack/echo
Pull request #1206 (2018-10-12 12:56:33)

Simplify tests
Simplify tests by initializing assert (no need to pass *testing.T to assert).

codecov[bot]: # [Codecov](https://codecov.io/gh/labstack/echo/pull/1206?src=pr&el=h1) Report
> Merging [#1206](https://codecov.io/gh/labstack/echo/pull/1206?src=pr&el=desc) into [master](https://codecov.io/gh/labstack/echo/commit/fcdf096c2c88f34b2ed0fb4cbefe8552bf930807?src=pr&el=desc) will **not change** coverage.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/labstack/echo/pull/1206/graphs/tree.svg?width=650&token=vqnT76l79i&height=150&src=pr)](https://codecov.io/gh/labstack/echo/pull/1206?src=pr&el=tree)

```diff
@@           Coverage Diff           @@
##           master    #1206   +/-   ##
=======================================
  Coverage   81.52%   81.52%           
=======================================
  Files          25       25           
  Lines        1921     1921           
=======================================
  Hits         1566     1566           
  Misses        248      248           
  Partials      107      107
```



------

[Continue to review full report at Codecov](https://codecov.io/gh/labstack/echo/pull/1206?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/labstack/echo/pull/1206?src=pr&el=footer). Last update [fcdf096...8705388](https://codecov.io/gh/labstack/echo/pull/1206?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/echo.go b/echo.go
index 2b3b8eb..3c03659 100644
--- a/echo.go
+++ b/echo.go
@@ -260,6 +260,7 @@ var (
 	ErrBadGateway                  = NewHTTPError(http.StatusBadGateway)
 	ErrInternalServerError         = NewHTTPError(http.StatusInternalServerError)
 	ErrRequestTimeout              = NewHTTPError(http.StatusRequestTimeout)
+	ErrServiceUnavailable          = NewHTTPError(http.StatusServiceUnavailable)
 	ErrValidatorNotRegistered      = errors.New("validator not registered")
 	ErrRendererNotRegistered       = errors.New("renderer not registered")
 	ErrInvalidRedirectCode         = errors.New("invalid redirect status code")
diff --git a/middleware/proxy.go b/middleware/proxy.go
index 2686c30..1789c75 100644
--- a/middleware/proxy.go
+++ b/middleware/proxy.go
@@ -6,7 +6,6 @@ import (
 	"math/rand"
 	"net"
 	"net/http"
-	"net/http/httputil"
 	"net/url"
 	"regexp"
 	"strings"
@@ -38,10 +37,14 @@ type (
 		// "/users/*/orders/*": "/user/$1/order/$2",
 		Rewrite map[string]string
 
-		// Context key to store selected ProxyTarget into context.
+    // Context key to store selected ProxyTarget into context.
 		// Optional. Default value "target".
 		ContextKey string
 
+    // To customize the transport to remote.
+		// Examples: If custom TLS certificates are required.
+		Transport http.RoundTripper
+
 		rewriteRegex map[*regexp.Regexp]string
 	}
 
@@ -85,10 +88,6 @@ var (
 	}
 )
 
-func proxyHTTP(t *ProxyTarget) http.Handler {
-	return httputil.NewSingleHostReverseProxy(t.URL)
-}
-
 func proxyRaw(t *ProxyTarget, c echo.Context) http.Handler {
 	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		in, _, err := c.Response().Hijack()
@@ -250,7 +249,7 @@ func ProxyWithConfig(config ProxyConfig) echo.MiddlewareFunc {
 				proxyRaw(tgt, c).ServeHTTP(res, req)
 			case req.Header.Get(echo.HeaderAccept) == "text/event-stream":
 			default:
-				proxyHTTP(tgt).ServeHTTP(res, req)
+				proxyHTTP(tgt, c, config).ServeHTTP(res, req)
 			}
 
 			return
diff --git a/middleware/proxy_1_11.go b/middleware/proxy_1_11.go
new file mode 100644
index 0000000..056c45f
--- /dev/null
+++ b/middleware/proxy_1_11.go
@@ -0,0 +1,25 @@
+// +build go1.11
+
+package middleware
+
+import (
+	"fmt"
+	"net/http"
+	"net/http/httputil"
+
+	"github.com/labstack/echo"
+)
+
+func proxyHTTP(tgt *ProxyTarget, c echo.Context, config ProxyConfig) http.Handler {
+	proxy := httputil.NewSingleHostReverseProxy(tgt.URL)
+	proxy.ErrorHandler = func(resp http.ResponseWriter, req *http.Request, err error) {
+		desc := tgt.URL.String()
+		if tgt.Name != "" {
+			desc = fmt.Sprintf("%s(%s)", tgt.Name, tgt.URL.String())
+		}
+		c.Logger().Errorf("remote %s unreachable, could not forward: %v", desc, err)
+		c.Error(echo.ErrServiceUnavailable)
+	}
+	proxy.Transport = config.Transport
+	return proxy
+}
diff --git a/middleware/proxy_1_11_n.go b/middleware/proxy_1_11_n.go
new file mode 100644
index 0000000..d4620e2
--- /dev/null
+++ b/middleware/proxy_1_11_n.go
@@ -0,0 +1,13 @@
+// +build !go1.11
+
+package middleware
+
+import (
+	"github.com/labstack/echo"
+	"net/http"
+	"net/http/httputil"
+)
+
+func proxyHTTP(t *ProxyTarget, c echo.Context, config ProxyConfig) http.Handler {
+	return httputil.NewSingleHostReverseProxy(t.URL)
+}


Test patch:
diff --git a/bind_test.go b/bind_test.go
index 72b0ed7..f4449c0 100644
--- a/bind_test.go
+++ b/bind_test.go
@@ -120,32 +120,37 @@ var values = map[string][]string{
 }
 
 func TestBindJSON(t *testing.T) {
-	testBindOkay(t, strings.NewReader(userJSON), MIMEApplicationJSON)
-	testBindError(t, strings.NewReader(invalidContent), MIMEApplicationJSON, &json.SyntaxError{})
-	testBindError(t, strings.NewReader(userJSONInvalidType), MIMEApplicationJSON, &json.UnmarshalTypeError{})
+	assert := assert.New(t)
+	testBindOkay(assert, strings.NewReader(userJSON), MIMEApplicationJSON)
+	testBindError(assert, strings.NewReader(invalidContent), MIMEApplicationJSON, &json.SyntaxError{})
+	testBindError(assert, strings.NewReader(userJSONInvalidType), MIMEApplicationJSON, &json.UnmarshalTypeError{})
 }
 
 func TestBindXML(t *testing.T) {
-	testBindOkay(t, strings.NewReader(userXML), MIMEApplicationXML)
-	testBindError(t, strings.NewReader(invalidContent), MIMEApplicationXML, errors.New(""))
-	testBindError(t, strings.NewReader(userXMLConvertNumberError), MIMEApplicationXML, &strconv.NumError{})
-	testBindError(t, strings.NewReader(userXMLUnsupportedTypeError), MIMEApplicationXML, &xml.SyntaxError{})
-	testBindOkay(t, strings.NewReader(userXML), MIMETextXML)
-	testBindError(t, strings.NewReader(invalidContent), MIMETextXML, errors.New(""))
-	testBindError(t, strings.NewReader(userXMLConvertNumberError), MIMETextXML, &strconv.NumError{})
-	testBindError(t, strings.NewReader(userXMLUnsupportedTypeError), MIMETextXML, &xml.SyntaxError{})
+	assert := assert.New(t)
+
+	testBindOkay(assert, strings.NewReader(userXML), MIMEApplicationXML)
+	testBindError(assert, strings.NewReader(invalidContent), MIMEApplicationXML, errors.New(""))
+	testBindError(assert, strings.NewReader(userXMLConvertNumberError), MIMEApplicationXML, &strconv.NumError{})
+	testBindError(assert, strings.NewReader(userXMLUnsupportedTypeError), MIMEApplicationXML, &xml.SyntaxError{})
+	testBindOkay(assert, strings.NewReader(userXML), MIMETextXML)
+	testBindError(assert, strings.NewReader(invalidContent), MIMETextXML, errors.New(""))
+	testBindError(assert, strings.NewReader(userXMLConvertNumberError), MIMETextXML, &strconv.NumError{})
+	testBindError(assert, strings.NewReader(userXMLUnsupportedTypeError), MIMETextXML, &xml.SyntaxError{})
 }
 
 func TestBindForm(t *testing.T) {
-	testBindOkay(t, strings.NewReader(userForm), MIMEApplicationForm)
-	testBindError(t, nil, MIMEApplicationForm, nil)
+	assert := assert.New(t)
+
+	testBindOkay(assert, strings.NewReader(userForm), MIMEApplicationForm)
+	testBindError(assert, nil, MIMEApplicationForm, nil)
 	e := New()
 	req := httptest.NewRequest(POST, "/", strings.NewReader(userForm))
 	rec := httptest.NewRecorder()
 	c := e.NewContext(req, rec)
 	req.Header.Set(HeaderContentType, MIMEApplicationForm)
 	err := c.Bind(&[]struct{ Field string }{})
-	assert.Error(t, err)
+	assert.Error(err)
 }
 
 func TestBindQueryParams(t *testing.T) {
@@ -200,12 +205,14 @@ func TestBindUnmarshalParam(t *testing.T) {
 	}{}
 	err := c.Bind(&result)
 	ts := Timestamp(time.Date(2016, 12, 6, 19, 9, 5, 0, time.UTC))
-	if assert.NoError(t, err) {
-		//		assert.Equal(t, Timestamp(reflect.TypeOf(&Timestamp{}), time.Date(2016, 12, 6, 19, 9, 5, 0, time.UTC)), result.T)
-		assert.Equal(t, ts, result.T)
-		assert.Equal(t, StringArray([]string{"one", "two", "three"}), result.SA)
-		assert.Equal(t, []Timestamp{ts, ts}, result.TA)
-		assert.Equal(t, Struct{"baz"}, result.ST)
+
+	assert := assert.New(t)
+	if assert.NoError(err) {
+		//		assert.Equal( Timestamp(reflect.TypeOf(&Timestamp{}), time.Date(2016, 12, 6, 19, 9, 5, 0, time.UTC)), result.T)
+		assert.Equal(ts, result.T)
+		assert.Equal(StringArray([]string{"one", "two", "three"}), result.SA)
+		assert.Equal([]Timestamp{ts, ts}, result.TA)
+		assert.Equal(Struct{"baz"}, result.ST)
 	}
 }
 
@@ -229,18 +236,22 @@ func TestBindMultipartForm(t *testing.T) {
 	mw.WriteField("id", "1")
 	mw.WriteField("name", "Jon Snow")
 	mw.Close()
-	testBindOkay(t, body, mw.FormDataContentType())
+
+	assert := assert.New(t)
+	testBindOkay(assert, body, mw.FormDataContentType())
 }
 
 func TestBindUnsupportedMediaType(t *testing.T) {
-	testBindError(t, strings.NewReader(invalidContent), MIMEApplicationJSON, &json.SyntaxError{})
+	assert := assert.New(t)
+	testBindError(assert, strings.NewReader(invalidContent), MIMEApplicationJSON, &json.SyntaxError{})
 }
 
 func TestBindbindData(t *testing.T) {
+	assert := assert.New(t)
 	ts := new(bindTestStruct)
 	b := new(DefaultBinder)
 	b.bindData(ts, values, "form")
-	assertBindTestStruct(t, ts)
+	assertBindTestStruct(assert, ts)
 }
 
 func TestBindUnmarshalTypeError(t *testing.T) {
@@ -261,6 +272,7 @@ func TestBindUnmarshalTypeError(t *testing.T) {
 }
 
 func TestBindSetWithProperType(t *testing.T) {
+	assert := assert.New(t)
 	ts := new(bindTestStruct)
 	typ := reflect.TypeOf(ts).Elem()
 	val := reflect.ValueOf(ts).Elem()
@@ -275,9 +287,9 @@ func TestBindSetWithProperType(t *testing.T) {
 		}
 		val := values[typeField.Name][0]
 		err := setWithProperType(typeField.Type.Kind(), val, structField)
-		assert.NoError(t, err)
+		assert.NoError(err)
 	}
-	assertBindTestStruct(t, ts)
+	assertBindTestStruct(assert, ts)
 
 	type foo struct {
 		Bar bytes.Buffer
@@ -285,70 +297,72 @@ func TestBindSetWithProperType(t *testing.T) {
 	v := &foo{}
 	typ = reflect.TypeOf(v).Elem()
 	val = reflect.ValueOf(v).Elem()
-	assert.Error(t, setWithProperType(typ.Field(0).Type.Kind(), "5", val.Field(0)))
+	assert.Error(setWithProperType(typ.Field(0).Type.Kind(), "5", val.Field(0)))
 }
 
 func TestBindSetFields(t *testing.T) {
+	assert := assert.New(t)
+
 	ts := new(bindTestStruct)
 	val := reflect.ValueOf(ts).Elem()
 	// Int
-	if assert.NoError(t, setIntField("5", 0, val.FieldByName("I"))) {
-		assert.Equal(t, 5, ts.I)
+	if assert.NoError(setIntField("5", 0, val.FieldByName("I"))) {
+		assert.Equal(5, ts.I)
 	}
-	if assert.NoError(t, setIntField("", 0, val.FieldByName("I"))) {
-		assert.Equal(t, 0, ts.I)
+	if assert.NoError(setIntField("", 0, val.FieldByName("I"))) {
+		assert.Equal(0, ts.I)
 	}
 
 	// Uint
-	if assert.NoError(t, setUintField("10", 0, val.FieldByName("UI"))) {
-		assert.Equal(t, uint(10), ts.UI)
+	if assert.NoError(setUintField("10", 0, val.FieldByName("UI"))) {
+		assert.Equal(uint(10), ts.UI)
 	}
-	if assert.NoError(t, setUintField("", 0, val.FieldByName("UI"))) {
-		assert.Equal(t, uint(0), ts.UI)
+	if assert.NoError(setUintField("", 0, val.FieldByName("UI"))) {
+		assert.Equal(uint(0), ts.UI)
 	}
 
 	// Float
-	if assert.NoError(t, setFloatField("15.5", 0, val.FieldByName("F32"))) {
-		assert.Equal(t, float32(15.5), ts.F32)
+	if assert.NoError(setFloatField("15.5", 0, val.FieldByName("F32"))) {
+		assert.Equal(float32(15.5), ts.F32)
 	}
-	if assert.NoError(t, setFloatField("", 0, val.FieldByName("F32"))) {
-		assert.Equal(t, float32(0.0), ts.F32)
+	if assert.NoError(setFloatField("", 0, val.FieldByName("F32"))) {
+		assert.Equal(float32(0.0), ts.F32)
 	}
 
 	// Bool
-	if assert.NoError(t, setBoolField("true", val.FieldByName("B"))) {
-		assert.Equal(t, true, ts.B)
+	if assert.NoError(setBoolField("true", val.FieldByName("B"))) {
+		assert.Equal(true, ts.B)
 	}
-	if assert.NoError(t, setBoolField("", val.FieldByName("B"))) {
-		assert.Equal(t, false, ts.B)
+	if assert.NoError(setBoolField("", val.FieldByName("B"))) {
+		assert.Equal(false, ts.B)
 	}
 
 	ok, err := unmarshalFieldNonPtr("2016-12-06T19:09:05Z", val.FieldByName("T"))
-	if assert.NoError(t, err) {
-		assert.Equal(t, ok, true)
-		assert.Equal(t, Timestamp(time.Date(2016, 12, 6, 19, 9, 5, 0, time.UTC)), ts.T)
+	if assert.NoError(err) {
+		assert.Equal(ok, true)
+		assert.Equal(Timestamp(time.Date(2016, 12, 6, 19, 9, 5, 0, time.UTC)), ts.T)
 	}
 }
 
-func assertBindTestStruct(t *testing.T, ts *bindTestStruct) {
-	assert.Equal(t, 0, ts.I)
-	assert.Equal(t, int8(8), ts.I8)
-	assert.Equal(t, int16(16), ts.I16)
-	assert.Equal(t, int32(32), ts.I32)
-	assert.Equal(t, int64(64), ts.I64)
-	assert.Equal(t, uint(0), ts.UI)
-	assert.Equal(t, uint8(8), ts.UI8)
-	assert.Equal(t, uint16(16), ts.UI16)
-	assert.Equal(t, uint32(32), ts.UI32)
-	assert.Equal(t, uint64(64), ts.UI64)
-	assert.Equal(t, true, ts.B)
-	assert.Equal(t, float32(32.5), ts.F32)
-	assert.Equal(t, float64(64.5), ts.F64)
-	assert.Equal(t, "test", ts.S)
-	assert.Equal(t, "", ts.GetCantSet())
+func assertBindTestStruct(a *assert.Assertions, ts *bindTestStruct) {
+	a.Equal(0, ts.I)
+	a.Equal(int8(8), ts.I8)
+	a.Equal(int16(16), ts.I16)
+	a.Equal(int32(32), ts.I32)
+	a.Equal(int64(64), ts.I64)
+	a.Equal(uint(0), ts.UI)
+	a.Equal(uint8(8), ts.UI8)
+	a.Equal(uint16(16), ts.UI16)
+	a.Equal(uint32(32), ts.UI32)
+	a.Equal(uint64(64), ts.UI64)
+	a.Equal(true, ts.B)
+	a.Equal(float32(32.5), ts.F32)
+	a.Equal(float64(64.5), ts.F64)
+	a.Equal("test", ts.S)
+	a.Equal("", ts.GetCantSet())
 }
 
-func testBindOkay(t *testing.T, r io.Reader, ctype string) {
+func testBindOkay(assert *assert.Assertions, r io.Reader, ctype string) {
 	e := New()
 	req := httptest.NewRequest(POST, "/", r)
 	rec := httptest.NewRecorder()
@@ -356,13 +370,13 @@ func testBindOkay(t *testing.T, r io.Reader, ctype string) {
 	req.Header.Set(HeaderContentType, ctype)
 	u := new(user)
 	err := c.Bind(u)
-	if assert.NoError(t, err) {
-		assert.Equal(t, 1, u.ID)
-		assert.Equal(t, "Jon Snow", u.Name)
+	if assert.NoError(err) {
+		assert.Equal(1, u.ID)
+		assert.Equal("Jon Snow", u.Name)
 	}
 }
 
-func testBindError(t *testing.T, r io.Reader, ctype string, expectedInternal error) {
+func testBindError(assert *assert.Assertions, r io.Reader, ctype string, expectedInternal error) {
 	e := New()
 	req := httptest.NewRequest(POST, "/", r)
 	rec := httptest.NewRecorder()
@@ -374,14 +388,14 @@ func testBindError(t *testing.T, r io.Reader, ctype string, expectedInternal err
 	switch {
 	case strings.HasPrefix(ctype, MIMEApplicationJSON), strings.HasPrefix(ctype, MIMEApplicationXML), strings.HasPrefix(ctype, MIMETextXML),
 		strings.HasPrefix(ctype, MIMEApplicationForm), strings.HasPrefix(ctype, MIMEMultipartForm):
-		if assert.IsType(t, new(HTTPError), err) {
-			assert.Equal(t, http.StatusBadRequest, err.(*HTTPError).Code)
-			assert.IsType(t, expectedInternal, err.(*HTTPError).Internal)
+		if assert.IsType(new(HTTPError), err) {
+			assert.Equal(http.StatusBadRequest, err.(*HTTPError).Code)
+			assert.IsType(expectedInternal, err.(*HTTPError).Internal)
 		}
 	default:
-		if assert.IsType(t, new(HTTPError), err) {
-			assert.Equal(t, ErrUnsupportedMediaType, err)
-			assert.IsType(t, expectedInternal, err.(*HTTPError).Internal)
+		if assert.IsType(new(HTTPError), err) {
+			assert.Equal(ErrUnsupportedMediaType, err)
+			assert.IsType(expectedInternal, err.(*HTTPError).Internal)
 		}
 	}
 }
diff --git a/context_test.go b/context_test.go
index bcbf975..10154e0 100644
--- a/context_test.go
+++ b/context_test.go
@@ -33,14 +33,16 @@ func TestContext(t *testing.T) {
 	rec := httptest.NewRecorder()
 	c := e.NewContext(req, rec).(*context)
 
+	assert := assert.New(t)
+
 	// Echo
-	assert.Equal(t, e, c.Echo())
+	assert.Equal(e, c.Echo())
 
 	// Request
-	assert.NotNil(t, c.Request())
+	assert.NotNil(c.Request())
 
 	// Response
-	assert.NotNil(t, c.Response())
+	assert.NotNil(c.Response())
 
 	//--------
 	// Render
@@ -51,23 +53,23 @@ func TestContext(t *testing.T) {
 	}
 	c.echo.Renderer = tmpl
 	err := c.Render(http.StatusOK, "hello", "Jon Snow")
-	if assert.NoError(t, err) {
-		assert.Equal(t, http.StatusOK, rec.Code)
-		assert.Equal(t, "Hello, Jon Snow!", rec.Body.String())
+	if assert.NoError(err) {
+		assert.Equal(http.StatusOK, rec.Code)
+		assert.Equal("Hello, Jon Snow!", rec.Body.String())
 	}
 
 	c.echo.Renderer = nil
 	err = c.Render(http.StatusOK, "hello", "Jon Snow")
-	assert.Error(t, err)
+	assert.Error(err)
 
 	// JSON
 	rec = httptest.NewRecorder()
 	c = e.NewContext(req, rec).(*context)
 	err = c.JSON(http.StatusOK, user{1, "Jon Snow"})
-	if assert.NoError(t, err) {
-		assert.Equal(t, http.StatusOK, rec.Code)
-		assert.Equal(t, MIMEApplicationJSONCharsetUTF8, rec.Header().Get(HeaderContentType))
-		assert.Equal(t, userJSON, rec.Body.String())
+	if assert.NoError(err) {
+		assert.Equal(http.StatusOK, rec.Code)
+		assert.Equal(MIMEApplicationJSONCharsetUTF8, rec.Header().Get(HeaderContentType))
+		assert.Equal(userJSON, rec.Body.String())
 	}
 
 	// JSON with "?pretty"
@@ -75,10 +77,10 @@ func TestContext(t *testing.T) {
 	rec = httptest.NewRecorder()
 	c = e.NewContext(req, rec).(*context)
 	err = c.JSON(http.StatusOK, user{1, "Jon Snow"})
-	if assert.NoError(t, err) {
-		assert.Equal(t, http.StatusOK, rec.Code)
-		assert.Equal(t, MIMEApplicationJSONCharsetUTF8, rec.Header().Get(HeaderContentType))
-		assert.Equal(t, userJSONPretty, rec.Body.String())
+	if assert.NoError(err) {
+		assert.Equal(http.StatusOK, rec.Code)
+		assert.Equal(MIMEApplicationJSONCharsetUTF8, rec.Header().Get(HeaderContentType))
+		assert.Equal(userJSONPretty, rec.Body.String())
 	}
 	req = httptest.NewRequest(GET, "/", nil) // reset
 
@@ -86,37 +88,37 @@ func TestContext(t *testing.T) {
 	rec = httptest.NewRecorder()
 	c = e.NewContext(req, rec).(*context)
 	err = c.JSONPretty(http.StatusOK, user{1, "Jon Snow"}, "  ")
-	if assert.NoError(t, err) {
-		assert.Equal(t, http.StatusOK, rec.Code)
-		assert.Equal(t, MIMEApplicationJSONCharsetUTF8, rec.Header().Get(HeaderContentType))
-		assert.Equal(t, userJSONPretty, rec.Body.String())
+	if assert.NoError(err) {
+		assert.Equal(http.StatusOK, rec.Code)
+		assert.Equal(MIMEApplicationJSONCharsetUTF8, rec.Header().Get(HeaderContentType))
+		assert.Equal(userJSONPretty, rec.Body.String())
 	}
 
 	// JSON (error)
 	rec = httptest.NewRecorder()
 	c = e.NewContext(req, rec).(*context)
 	err = c.JSON(http.StatusOK, make(chan bool))
-	assert.Error(t, err)
+	assert.Error(err)
 
 	// JSONP
 	rec = httptest.NewRecorder()
 	c = e.NewContext(req, rec).(*context)
 	callback := "callback"
 	err = c.JSONP(http.StatusOK, callback, user{1, "Jon Snow"})
-	if assert.NoError(t, err) {
-		assert.Equal(t, http.StatusOK, rec.Code)
-		assert.Equal(t, MIMEApplicationJavaScriptCharsetUTF8, rec.Header().Get(HeaderContentType))
-		assert.Equal(t, callback+"("+userJSON+");", rec.Body.String())
+	if assert.NoError(err) {
+		assert.Equal(http.StatusOK, rec.Code)
+		assert.Equal(MIMEApplicationJavaScriptCharsetUTF8, rec.Header().Get(HeaderContentType))
+		assert.Equal(callback+"("+userJSON+");", rec.Body.String())
 	}
 
 	// XML
 	rec = httptest.NewRecorder()
 	c = e.NewContext(req, rec).(*context)
 	err = c.XML(http.StatusOK, user{1, "Jon Snow"})
-	if assert.NoError(t, err) {
-		assert.Equal(t, http.StatusOK, rec.Code)
-		assert.Equal(t, MIMEApplicationXMLCharsetUTF8, rec.Header().Get(HeaderContentType))
-		assert.Equal(t, xml.Header+userXML, rec.Body.String())
+	if assert.NoError(err) {
+		assert.Equal(http.StatusOK, rec.Code)
+		assert.Equal(MIMEApplicationXMLCharsetUTF8, rec.Header().Get(HeaderContentType))
+		assert.Equal(xml.Header+userXML, rec.Body.String())
 	}
 
 	// XML with "?pretty"
@@ -124,10 +126,10 @@ func TestContext(t *testing.T) {
 	rec = httptest.NewRecorder()
 	c = e.NewContext(req, rec).(*context)
 	err = c.XML(http.StatusOK, user{1, "Jon Snow"})
-	if assert.NoError(t, err) {
-		assert.Equal(t, http.StatusOK, rec.Code)
-		assert.Equal(t, MIMEApplicationXMLCharsetUTF8, rec.Header().Get(HeaderContentType))
-		assert.Equal(t, xml.Header+userXMLPretty, rec.Body.String())
+	if assert.NoError(err) {
+		assert.Equal(http.StatusOK, rec.Code)
+		assert.Equal(MIMEApplicationXMLCharsetUTF8, rec.Header().Get(HeaderContentType))
+		assert.Equal(xml.Header+userXMLPretty, rec.Body.String())
 	}
 	req = httptest.NewRequest(GET, "/", nil)
 
@@ -135,36 +137,36 @@ func TestContext(t *testing.T) {
 	rec = httptest.NewRecorder()
 	c = e.NewContext(req, rec).(*context)
 	err = c.XML(http.StatusOK, make(chan bool))
-	assert.Error(t, err)
+	assert.Error(err)
 
 	// XMLPretty
 	rec = httptest.NewRecorder()
 	c = e.NewContext(req, rec).(*context)
 	err = c.XMLPretty(http.StatusOK, user{1, "Jon Snow"}, "  ")
-	if assert.NoError(t, err) {
-		assert.Equal(t, http.StatusOK, rec.Code)
-		assert.Equal(t, MIMEApplicationXMLCharsetUTF8, rec.Header().Get(HeaderContentType))
-		assert.Equal(t, xml.Header+userXMLPretty, rec.Body.String())
+	if assert.NoError(err) {
+		assert.Equal(http.StatusOK, rec.Code)
+		assert.Equal(MIMEApplicationXMLCharsetUTF8, rec.Header().Get(HeaderContentType))
+		assert.Equal(xml.Header+userXMLPretty, rec.Body.String())
 	}
 
 	// String
 	rec = httptest.NewRecorder()
 	c = e.NewContext(req, rec).(*context)
 	err = c.String(http.StatusOK, "Hello, World!")
-	if assert.NoError(t, err) {
-		assert.Equal(t, http.StatusOK, rec.Code)
-		assert.Equal(t, MIMETextPlainCharsetUTF8, rec.Header().Get(HeaderContentType))
-		assert.Equal(t, "Hello, World!", rec.Body.String())
+	if assert.NoError(err) {
+		assert.Equal(http.StatusOK, rec.Code)
+		assert.Equal(MIMETextPlainCharsetUTF8, rec.Header().Get(HeaderContentType))
+		assert.Equal("Hello, World!", rec.Body.String())
 	}
 
 	// HTML
 	rec = httptest.NewRecorder()
 	c = e.NewContext(req, rec).(*context)
 	err = c.HTML(http.StatusOK, "Hello, <strong>World!</strong>")
-	if assert.NoError(t, err) {
-		assert.Equal(t, http.StatusOK, rec.Code)
-		assert.Equal(t, MIMETextHTMLCharsetUTF8, rec.Header().Get(HeaderContentType))
-		assert.Equal(t, "Hello, <strong>World!</strong>", rec.Body.String())
+	if assert.NoError(err) {
+		assert.Equal(http.StatusOK, rec.Code)
+		assert.Equal(MIMETextHTMLCharsetUTF8, rec.Header().Get(HeaderContentType))
+		assert.Equal("Hello, <strong>World!</strong>", rec.Body.String())
 	}
 
 	// Stream
@@ -172,43 +174,43 @@ func TestContext(t *testing.T) {
 	c = e.NewContext(req, rec).(*context)
 	r := strings.NewReader("response from a stream")
 	err = c.Stream(http.StatusOK, "application/octet-stream", r)
-	if assert.NoError(t, err) {
-		assert.Equal(t, http.StatusOK, rec.Code)
-		assert.Equal(t, "application/octet-stream", rec.Header().Get(HeaderContentType))
-		assert.Equal(t, "response from a stream", rec.Body.String())
+	if assert.NoError(err) {
+		assert.Equal(http.StatusOK, rec.Code)
+		assert.Equal("application/octet-stream", rec.Header().Get(HeaderContentType))
+		assert.Equal("response from a stream", rec.Body.String())
 	}
 
 	// Attachment
 	rec = httptest.NewRecorder()
 	c = e.NewContext(req, rec).(*context)
 	err = c.Attachment("_fixture/images/walle.png", "walle.png")
-	if assert.NoError(t, err) {
-		assert.Equal(t, http.StatusOK, rec.Code)
-		assert.Equal(t, "attachment; filename=\"walle.png\"", rec.Header().Get(HeaderContentDisposition))
-		assert.Equal(t, 219885, rec.Body.Len())
+	if assert.NoError(err) {
+		assert.Equal(http.StatusOK, rec.Code)
+		assert.Equal("attachment; filename=\"walle.png\"", rec.Header().Get(HeaderContentDisposition))
+		assert.Equal(219885, rec.Body.Len())
 	}
 
 	// Inline
 	rec = httptest.NewRecorder()
 	c = e.NewContext(req, rec).(*context)
 	err = c.Inline("_fixture/images/walle.png", "walle.png")
-	if assert.NoError(t, err) {
-		assert.Equal(t, http.StatusOK, rec.Code)
-		assert.Equal(t, "inline; filename=\"walle.png\"", rec.Header().Get(HeaderContentDisposition))
-		assert.Equal(t, 219885, rec.Body.Len())
+	if assert.NoError(err) {
+		assert.Equal(http.StatusOK, rec.Code)
+		assert.Equal("inline; filename=\"walle.png\"", rec.Header().Get(HeaderContentDisposition))
+		assert.Equal(219885, rec.Body.Len())
 	}
 
 	// NoContent
 	rec = httptest.NewRecorder()
 	c = e.NewContext(req, rec).(*context)
 	c.NoContent(http.StatusOK)
-	assert.Equal(t, http.StatusOK, rec.Code)
+	assert.Equal(http.StatusOK, rec.Code)
 
 	// Error
 	rec = httptest.NewRecorder()
 	c = e.NewContext(req, rec).(*context)
 	c.Error(errors.New("error"))
-	assert.Equal(t, http.StatusInternalServerError, rec.Code)
+	assert.Equal(http.StatusInternalServerError, rec.Code)
 
 	// Reset
 	c.SetParamNames("foo")
@@ -216,11 +218,11 @@ func TestContext(t *testing.T) {
 	c.Set("foe", "ban")
 	c.query = url.Values(map[string][]string{"fon": {"baz"}})
 	c.Reset(req, httptest.NewRecorder())
-	assert.Equal(t, 0, len(c.ParamValues()))
-	assert.Equal(t, 0, len(c.ParamNames()))
-	assert.Equal(t, 0, len(c.store))
-	assert.Equal(t, "", c.Path())
-	assert.Equal(t, 0, len(c.QueryParams()))
+	assert.Equal(0, len(c.ParamValues()))
+	assert.Equal(0, len(c.ParamNames()))
+	assert.Equal(0, len(c.store))
+	assert.Equal("", c.Path())
+	assert.Equal(0, len(c.QueryParams()))
 }
 
 func TestContextCookie(t *testing.T) {
@@ -233,20 +235,22 @@ func TestContextCookie(t *testing.T) {
 	rec := httptest.NewRecorder()
 	c := e.NewContext(req, rec).(*context)
 
+	assert := assert.New(t)
+
 	// Read single
 	cookie, err := c.Cookie("theme")
-	if assert.NoError(t, err) {
-		assert.Equal(t, "theme", cookie.Name)
-		assert.Equal(t, "light", cookie.Value)
+	if assert.NoError(err) {
+		assert.Equal("theme", cookie.Name)
+		assert.Equal("light", cookie.Value)
 	}
 
 	// Read multiple
 	for _, cookie := range c.Cookies() {
 		switch cookie.Name {
 		case "theme":
-			assert.Equal(t, "light", cookie.Value)
+			assert.Equal("light", cookie.Value)
 		case "user":
-			assert.Equal(t, "Jon Snow", cookie.Value)
+			assert.Equal("Jon Snow", cookie.Value)
 		}
 	}
 
@@ -261,11 +265,11 @@ func TestContextCookie(t *testing.T) {
 		HttpOnly: true,
 	}
 	c.SetCookie(cookie)
-	assert.Contains(t, rec.Header().Get(HeaderSetCookie), "SSID")
-	assert.Contains(t, rec.Header().Get(HeaderSetCookie), "Ap4PGTEq")
-	assert.Contains(t, rec.Header().Get(HeaderSetCookie), "labstack.com")
-	assert.Contains(t, rec.Header().Get(HeaderSetCookie), "Secure")
-	assert.Contains(t, rec.Header().Get(HeaderSetCookie), "HttpOnly")
+	assert.Contains(rec.Header().Get(HeaderSetCookie), "SSID")
+	assert.Contains(rec.Header().Get(HeaderSetCookie), "Ap4PGTEq")
+	assert.Contains(rec.Header().Get(HeaderSetCookie), "labstack.com")
+	assert.Contains(rec.Header().Get(HeaderSetCookie), "Secure")
+	assert.Contains(rec.Header().Get(HeaderSetCookie), "HttpOnly")
 }
 
 func TestContextPath(t *testing.T) {
@@ -275,12 +279,15 @@ func TestContextPath(t *testing.T) {
 	r.Add(GET, "/users/:id", nil)
 	c := e.NewContext(nil, nil)
 	r.Find(GET, "/users/1", c)
-	assert.Equal(t, "/users/:id", c.Path())
+
+	assert := assert.New(t)
+
+	assert.Equal("/users/:id", c.Path())
 
 	r.Add(GET, "/users/:uid/files/:fid", nil)
 	c = e.NewContext(nil, nil)
 	r.Find(GET, "/users/1/files/1", c)
-	assert.Equal(t, "/users/:uid/files/:fid", c.Path())
+	assert.Equal("/users/:uid/files/:fid", c.Path())
 }
 
 func TestContextPathParam(t *testing.T) {
diff --git a/echo_test.go b/echo_test.go
index 6bd1941..03932f7 100644
--- a/echo_test.go
+++ b/echo_test.go
@@ -58,32 +58,34 @@ func TestEcho(t *testing.T) {
 func TestEchoStatic(t *testing.T) {
 	e := New()
 
+	assert := assert.New(t)
+
 	// OK
 	e.Static("/images", "_fixture/images")
 	c, b := request(GET, "/images/walle.png", e)
-	assert.Equal(t, http.StatusOK, c)
-	assert.NotEmpty(t, b)
+	assert.Equal(http.StatusOK, c)
+	assert.NotEmpty(b)
 
 	// No file
 	e.Static("/images", "_fixture/scripts")
 	c, _ = request(GET, "/images/bolt.png", e)
-	assert.Equal(t, http.StatusNotFound, c)
+	assert.Equal(http.StatusNotFound, c)
 
 	// Directory
 	e.Static("/images", "_fixture/images")
 	c, _ = request(GET, "/images", e)
-	assert.Equal(t, http.StatusNotFound, c)
+	assert.Equal(http.StatusNotFound, c)
 
 	// Directory with index.html
 	e.Static("/", "_fixture")
 	c, r := request(GET, "/", e)
-	assert.Equal(t, http.StatusOK, c)
-	assert.Equal(t, true, strings.HasPrefix(r, "<!doctype html>"))
+	assert.Equal(http.StatusOK, c)
+	assert.Equal(true, strings.HasPrefix(r, "<!doctype html>"))
 
 	// Sub-directory with index.html
 	c, r = request(GET, "/folder", e)
-	assert.Equal(t, http.StatusOK, c)
-	assert.Equal(t, true, strings.HasPrefix(r, "<!doctype html>"))
+	assert.Equal(http.StatusOK, c)
+	assert.Equal(true, strings.HasPrefix(r, "<!doctype html>"))
 }
 
 func TestEchoFile(t *testing.T) {
@@ -270,11 +272,13 @@ func TestEchoURL(t *testing.T) {
 	g := e.Group("/group")
 	g.GET("/users/:uid/files/:fid", getFile)
 
-	assert.Equal(t, "/static/file", e.URL(static))
-	assert.Equal(t, "/users/:id", e.URL(getUser))
-	assert.Equal(t, "/users/1", e.URL(getUser, "1"))
-	assert.Equal(t, "/group/users/1/files/:fid", e.URL(getFile, "1"))
-	assert.Equal(t, "/group/users/1/files/1", e.URL(getFile, "1", "1"))
+	assert := assert.New(t)
+
+	assert.Equal("/static/file", e.URL(static))
+	assert.Equal("/users/:id", e.URL(getUser))
+	assert.Equal("/users/1", e.URL(getUser, "1"))
+	assert.Equal("/group/users/1/files/:fid", e.URL(getFile, "1"))
+	assert.Equal("/group/users/1/files/1", e.URL(getFile, "1", "1"))
 }
 
 func TestEchoRoutes(t *testing.T) {
diff --git a/middleware/basic_auth_test.go b/middleware/basic_auth_test.go
index 9302322..93271f1 100644
--- a/middleware/basic_auth_test.go
+++ b/middleware/basic_auth_test.go
@@ -26,10 +26,12 @@ func TestBasicAuth(t *testing.T) {
 		return c.String(http.StatusOK, "test")
 	})
 
+	assert := assert.New(t)
+
 	// Valid credentials
 	auth := basic + " " + base64.StdEncoding.EncodeToString([]byte("joe:secret"))
 	req.Header.Set(echo.HeaderAuthorization, auth)
-	assert.NoError(t, h(c))
+	assert.NoError(h(c))
 
 	h = BasicAuthWithConfig(BasicAuthConfig{
 		Skipper:   nil,
@@ -42,28 +44,28 @@ func TestBasicAuth(t *testing.T) {
 	// Valid credentials
 	auth = basic + " " + base64.StdEncoding.EncodeToString([]byte("joe:secret"))
 	req.Header.Set(echo.HeaderAuthorization, auth)
-	assert.NoError(t, h(c))
+	assert.NoError(h(c))
 
 	// Case-insensitive header scheme
 	auth = strings.ToUpper(basic) + " " + base64.StdEncoding.EncodeToString([]byte("joe:secret"))
 	req.Header.Set(echo.HeaderAuthorization, auth)
-	assert.NoError(t, h(c))
+	assert.NoError(h(c))
 
 	// Invalid credentials
 	auth = basic + " " + base64.StdEncoding.EncodeToString([]byte("joe:invalid-password"))
 	req.Header.Set(echo.HeaderAuthorization, auth)
 	he := h(c).(*echo.HTTPError)
-	assert.Equal(t, http.StatusUnauthorized, he.Code)
-	assert.Equal(t, basic+` realm="someRealm"`, res.Header().Get(echo.HeaderWWWAuthenticate))
+	assert.Equal(http.StatusUnauthorized, he.Code)
+	assert.Equal(basic+` realm="someRealm"`, res.Header().Get(echo.HeaderWWWAuthenticate))
 
 	// Missing Authorization header
 	req.Header.Del(echo.HeaderAuthorization)
 	he = h(c).(*echo.HTTPError)
-	assert.Equal(t, http.StatusUnauthorized, he.Code)
+	assert.Equal(http.StatusUnauthorized, he.Code)
 
 	// Invalid Authorization header
 	auth = base64.StdEncoding.EncodeToString([]byte("invalid"))
 	req.Header.Set(echo.HeaderAuthorization, auth)
 	he = h(c).(*echo.HTTPError)
-	assert.Equal(t, http.StatusUnauthorized, he.Code)
+	assert.Equal(http.StatusUnauthorized, he.Code)
 }
diff --git a/middleware/body_dump_test.go b/middleware/body_dump_test.go
index 8649034..e1589b5 100644
--- a/middleware/body_dump_test.go
+++ b/middleware/body_dump_test.go
@@ -33,11 +33,13 @@ func TestBodyDump(t *testing.T) {
 		responseBody = string(resBody)
 	})
 
-	if assert.NoError(t, mw(h)(c)) {
-		assert.Equal(t, requestBody, hw)
-		assert.Equal(t, responseBody, hw)
-		assert.Equal(t, http.StatusOK, rec.Code)
-		assert.Equal(t, hw, rec.Body.String())
+	assert := assert.New(t)
+
+	if assert.NoError(mw(h)(c)) {
+		assert.Equal(requestBody, hw)
+		assert.Equal(responseBody, hw)
+		assert.Equal(http.StatusOK, rec.Code)
+		assert.Equal(hw, rec.Body.String())
 	}
 
 	// Must set default skipper
diff --git a/middleware/body_limit_test.go b/middleware/body_limit_test.go
index b3329f1..392f6b3 100644
--- a/middleware/body_limit_test.go
+++ b/middleware/body_limit_test.go
@@ -25,23 +25,25 @@ func TestBodyLimit(t *testing.T) {
 		return c.String(http.StatusOK, string(body))
 	}
 
+	assert := assert.New(t)
+
 	// Based on content length (within limit)
-	if assert.NoError(t, BodyLimit("2M")(h)(c)) {
-		assert.Equal(t, http.StatusOK, rec.Code)
-		assert.Equal(t, hw, rec.Body.Bytes())
+	if assert.NoError(BodyLimit("2M")(h)(c)) {
+		assert.Equal(http.StatusOK, rec.Code)
+		assert.Equal(hw, rec.Body.Bytes())
 	}
 
 	// Based on content read (overlimit)
 	he := BodyLimit("2B")(h)(c).(*echo.HTTPError)
-	assert.Equal(t, http.StatusRequestEntityTooLarge, he.Code)
+	assert.Equal(http.StatusRequestEntityTooLarge, he.Code)
 
 	// Based on content read (within limit)
 	req = httptest.NewRequest(echo.POST, "/", bytes.NewReader(hw))
 	rec = httptest.NewRecorder()
 	c = e.NewContext(req, rec)
-	if assert.NoError(t, BodyLimit("2M")(h)(c)) {
-		assert.Equal(t, http.StatusOK, rec.Code)
-		assert.Equal(t, "Hello, World!", rec.Body.String())
+	if assert.NoError(BodyLimit("2M")(h)(c)) {
+		assert.Equal(http.StatusOK, rec.Code)
+		assert.Equal("Hello, World!", rec.Body.String())
 	}
 
 	// Based on content read (overlimit)
@@ -49,7 +51,7 @@ func TestBodyLimit(t *testing.T) {
 	rec = httptest.NewRecorder()
 	c = e.NewContext(req, rec)
 	he = BodyLimit("2B")(h)(c).(*echo.HTTPError)
-	assert.Equal(t, http.StatusRequestEntityTooLarge, he.Code)
+	assert.Equal(http.StatusRequestEntityTooLarge, he.Code)
 }
 
 func TestBodyLimitReader(t *testing.T) {
diff --git a/middleware/compress_test.go b/middleware/compress_test.go
index d0408e6..956b9c4 100644
--- a/middleware/compress_test.go
+++ b/middleware/compress_test.go
@@ -24,7 +24,10 @@ func TestGzip(t *testing.T) {
 		return nil
 	})
 	h(c)
-	assert.Equal(t, "test", rec.Body.String())
+
+	assert := assert.New(t)
+
+	assert.Equal("test", rec.Body.String())
 
 	// Gzip
 	req = httptest.NewRequest(echo.GET, "/", nil)
@@ -32,14 +35,14 @@ func TestGzip(t *testing.T) {
 	rec = httptest.NewRecorder()
 	c = e.NewContext(req, rec)
 	h(c)
-	assert.Equal(t, gzipScheme, rec.Header().Get(echo.HeaderContentEncoding))
-	assert.Contains(t, rec.Header().Get(echo.HeaderContentType), echo.MIMETextPlain)
+	assert.Equal(gzipScheme, rec.Header().Get(echo.HeaderContentEncoding))
+	assert.Contains(rec.Header().Get(echo.HeaderContentType), echo.MIMETextPlain)
 	r, err := gzip.NewReader(rec.Body)
-	if assert.NoError(t, err) {
+	if assert.NoError(err) {
 		buf := new(bytes.Buffer)
 		defer r.Close()
 		buf.ReadFrom(r)
-		assert.Equal(t, "test", buf.String())
+		assert.Equal("test", buf.String())
 	}
 }
 
diff --git a/middleware/key_auth_test.go b/middleware/key_auth_test.go
index b5f4998..35ed85b 100644
--- a/middleware/key_auth_test.go
+++ b/middleware/key_auth_test.go
@@ -25,21 +25,23 @@ func TestKeyAuth(t *testing.T) {
 		return c.String(http.StatusOK, "test")
 	})
 
+	assert := assert.New(t)
+
 	// Valid key
 	auth := DefaultKeyAuthConfig.AuthScheme + " " + "valid-key"
 	req.Header.Set(echo.HeaderAuthorization, auth)
-	assert.NoError(t, h(c))
+	assert.NoError(h(c))
 
 	// Invalid key
 	auth = DefaultKeyAuthConfig.AuthScheme + " " + "invalid-key"
 	req.Header.Set(echo.HeaderAuthorization, auth)
 	he := h(c).(*echo.HTTPError)
-	assert.Equal(t, http.StatusUnauthorized, he.Code)
+	assert.Equal(http.StatusUnauthorized, he.Code)
 
 	// Missing Authorization header
 	req.Header.Del(echo.HeaderAuthorization)
 	he = h(c).(*echo.HTTPError)
-	assert.Equal(t, http.StatusBadRequest, he.Code)
+	assert.Equal(http.StatusBadRequest, he.Code)
 
 	// Key from custom header
 	config.KeyLookup = "header:API-Key"
@@ -47,7 +49,7 @@ func TestKeyAuth(t *testing.T) {
 		return c.String(http.StatusOK, "test")
 	})
 	req.Header.Set("API-Key", "valid-key")
-	assert.NoError(t, h(c))
+	assert.NoError(h(c))
 
 	// Key from query string
 	config.KeyLookup = "query:key"
@@ -57,7 +59,7 @@ func TestKeyAuth(t *testing.T) {
 	q := req.URL.Query()
 	q.Add("key", "valid-key")
 	req.URL.RawQuery = q.Encode()
-	assert.NoError(t, h(c))
+	assert.NoError(h(c))
 
 	// Key from form
 	config.KeyLookup = "form:key"
@@ -69,5 +71,5 @@ func TestKeyAuth(t *testing.T) {
 	req = httptest.NewRequest(echo.POST, "/", strings.NewReader(f.Encode()))
 	req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationForm)
 	c = e.NewContext(req, rec)
-	assert.NoError(t, h(c))
+	assert.NoError(h(c))
 }
diff --git a/middleware/proxy_1_11_test.go b/middleware/proxy_1_11_test.go
new file mode 100644
index 0000000..19bbc26
--- /dev/null
+++ b/middleware/proxy_1_11_test.go
@@ -0,0 +1,52 @@
+// +build go1.11
+
+package middleware
+
+import (
+	"github.com/labstack/echo"
+	"github.com/stretchr/testify/assert"
+	"net/http"
+	"net/http/httptest"
+	"net/url"
+	"testing"
+)
+
+func TestProxy_1_11(t *testing.T) {
+	// Setup
+	url1, _ := url.Parse("http://127.0.0.1:27121")
+	url2, _ := url.Parse("http://127.0.0.1:27122")
+
+	targets := []*ProxyTarget{
+		{
+			Name: "target 1",
+			URL:  url1,
+		},
+		{
+			Name: "target 2",
+			URL:  url2,
+		},
+	}
+	rb := NewRandomBalancer(nil)
+	// must add targets:
+	for _, target := range targets {
+		assert.True(t, rb.AddTarget(target))
+	}
+
+	// must ignore duplicates:
+	for _, target := range targets {
+		assert.False(t, rb.AddTarget(target))
+	}
+
+	// Random
+	e := echo.New()
+	e.Use(Proxy(rb))
+	req := httptest.NewRequest(echo.GET, "/", nil)
+	rec := newCloseNotifyRecorder()
+
+	// Remote unreachable
+	rec = newCloseNotifyRecorder()
+	req.URL.Path = "/api/users"
+	e.ServeHTTP(rec, req)
+	assert.Equal(t, "/api/users", req.URL.Path)
+	assert.Equal(t, http.StatusServiceUnavailable, rec.Code)
+}
diff --git a/middleware/proxy_test.go b/middleware/proxy_test.go
index 3a79b83..d003941 100644
--- a/middleware/proxy_test.go
+++ b/middleware/proxy_test.go
@@ -124,6 +124,7 @@ func TestProxy(t *testing.T) {
 	req.URL.Path = "/users/jack/orders/1"
 	e.ServeHTTP(rec, req)
 	assert.Equal(t, "/user/jack/order/1", req.URL.Path)
+	assert.Equal(t, http.StatusOK, rec.Code)
 
 	// ProxyTarget is set in context
 	contextObserver := func(next echo.HandlerFunc) echo.HandlerFunc {
diff --git a/middleware/rewrite_test.go b/middleware/rewrite_test.go
index 667f1fc..1768856 100644
--- a/middleware/rewrite_test.go
+++ b/middleware/rewrite_test.go
@@ -53,7 +53,6 @@ func TestEchoRewritePreMiddleware(t *testing.T) {
 	// Route
 	r.Add(echo.GET, "/new", func(c echo.Context) error {
 		return c.NoContent(200)
-		return nil
 	})
 
 	req := httptest.NewRequest(echo.GET, "/old", nil)
diff --git a/middleware/slash_test.go b/middleware/slash_test.go
index f1ffdb0..4f48aaa 100644
--- a/middleware/slash_test.go
+++ b/middleware/slash_test.go
@@ -18,8 +18,10 @@ func TestAddTrailingSlash(t *testing.T) {
 		return nil
 	})
 	h(c)
-	assert.Equal(t, "/add-slash/", req.URL.Path)
-	assert.Equal(t, "/add-slash/", req.RequestURI)
+
+	assert := assert.New(t)
+	assert.Equal("/add-slash/", req.URL.Path)
+	assert.Equal("/add-slash/", req.RequestURI)
 
 	// With config
 	req = httptest.NewRequest(echo.GET, "/add-slash?key=value", nil)
@@ -31,8 +33,8 @@ func TestAddTrailingSlash(t *testing.T) {
 		return nil
 	})
 	h(c)
-	assert.Equal(t, http.StatusMovedPermanently, rec.Code)
-	assert.Equal(t, "/add-slash/?key=value", rec.Header().Get(echo.HeaderLocation))
+	assert.Equal(http.StatusMovedPermanently, rec.Code)
+	assert.Equal("/add-slash/?key=value", rec.Header().Get(echo.HeaderLocation))
 }
 
 func TestRemoveTrailingSlash(t *testing.T) {
@@ -44,8 +46,11 @@ func TestRemoveTrailingSlash(t *testing.T) {
 		return nil
 	})
 	h(c)
-	assert.Equal(t, "/remove-slash", req.URL.Path)
-	assert.Equal(t, "/remove-slash", req.RequestURI)
+
+	assert := assert.New(t)
+
+	assert.Equal("/remove-slash", req.URL.Path)
+	assert.Equal("/remove-slash", req.RequestURI)
 
 	// With config
 	req = httptest.NewRequest(echo.GET, "/remove-slash/?key=value", nil)
@@ -57,8 +62,8 @@ func TestRemoveTrailingSlash(t *testing.T) {
 		return nil
 	})
 	h(c)
-	assert.Equal(t, http.StatusMovedPermanently, rec.Code)
-	assert.Equal(t, "/remove-slash?key=value", rec.Header().Get(echo.HeaderLocation))
+	assert.Equal(http.StatusMovedPermanently, rec.Code)
+	assert.Equal("/remove-slash?key=value", rec.Header().Get(echo.HeaderLocation))
 
 	// With bare URL
 	req = httptest.NewRequest(echo.GET, "http://localhost", nil)
@@ -68,5 +73,5 @@ func TestRemoveTrailingSlash(t *testing.T) {
 		return nil
 	})
 	h(c)
-	assert.Equal(t, "", req.URL.Path)
+	assert.Equal("", req.URL.Path)
 }
diff --git a/middleware/static_test.go b/middleware/static_test.go
index 7833f56..3e9f51e 100644
--- a/middleware/static_test.go
+++ b/middleware/static_test.go
@@ -20,17 +20,20 @@ func TestStatic(t *testing.T) {
 
 	// Directory
 	h := StaticWithConfig(config)(echo.NotFoundHandler)
-	if assert.NoError(t, h(c)) {
-		assert.Contains(t, rec.Body.String(), "Echo")
+
+	assert := assert.New(t)
+
+	if assert.NoError(h(c)) {
+		assert.Contains(rec.Body.String(), "Echo")
 	}
 
 	// File found
 	req = httptest.NewRequest(echo.GET, "/images/walle.png", nil)
 	rec = httptest.NewRecorder()
 	c = e.NewContext(req, rec)
-	if assert.NoError(t, h(c)) {
-		assert.Equal(t, http.StatusOK, rec.Code)
-		assert.Equal(t, rec.Header().Get(echo.HeaderContentLength), "219885")
+	if assert.NoError(h(c)) {
+		assert.Equal(http.StatusOK, rec.Code)
+		assert.Equal(rec.Header().Get(echo.HeaderContentLength), "219885")
 	}
 
 	// File not found
@@ -38,7 +41,7 @@ func TestStatic(t *testing.T) {
 	rec = httptest.NewRecorder()
 	c = e.NewContext(req, rec)
 	he := h(c).(*echo.HTTPError)
-	assert.Equal(t, http.StatusNotFound, he.Code)
+	assert.Equal(http.StatusNotFound, he.Code)
 
 	// HTML5
 	req = httptest.NewRequest(echo.GET, "/random", nil)
@@ -47,9 +50,9 @@ func TestStatic(t *testing.T) {
 	config.HTML5 = true
 	static := StaticWithConfig(config)
 	h = static(echo.NotFoundHandler)
-	if assert.NoError(t, h(c)) {
-		assert.Equal(t, http.StatusOK, rec.Code)
-		assert.Contains(t, rec.Body.String(), "Echo")
+	if assert.NoError(h(c)) {
+		assert.Equal(http.StatusOK, rec.Code)
+		assert.Contains(rec.Body.String(), "Echo")
 	}
 
 	// Browse
@@ -60,8 +63,8 @@ func TestStatic(t *testing.T) {
 	config.Browse = true
 	static = StaticWithConfig(config)
 	h = static(echo.NotFoundHandler)
-	if assert.NoError(t, h(c)) {
-		assert.Equal(t, http.StatusOK, rec.Code)
-		assert.Contains(t, rec.Body.String(), "cert.pem")
+	if assert.NoError(h(c)) {
+		assert.Equal(http.StatusOK, rec.Code)
+		assert.Contains(rec.Body.String(), "cert.pem")
 	}
 }