diff --git a/remoting/etcdv3/client_test.go b/remoting/etcdv3/client_test.go
index 00bbfbb57beb03ff44184b3ea99c768f628d937d..6f6bbff9b77e79c8b98b099d6eae22ab4243c21e 100644
--- a/remoting/etcdv3/client_test.go
+++ b/remoting/etcdv3/client_test.go
@@ -1,6 +1,7 @@
 package etcdv3
 
 import (
+	"fmt"
 	"os"
 	"os/exec"
 	"path"
@@ -10,19 +11,13 @@ import (
 	"testing"
 	"time"
 
+	"github.com/stretchr/testify/suite"
+
 	"github.com/coreos/etcd/mvcc/mvccpb"
 	"github.com/juju/errors"
 	"google.golang.org/grpc/connectivity"
 )
 
-// etcd connect config
-var (
-	name      = "test"
-	timeout   = time.Second
-	heartbeat = 1
-	endpoints = []string{"localhost:2379"}
-)
-
 // tests dataset
 var tests = []struct {
 	input struct {
@@ -51,69 +46,111 @@ var tests = []struct {
 // test dataset prefix
 const prefix = "name"
 
-func initClient(t *testing.T) *Client {
+type ClientTestSuite struct {
+	suite.Suite
 
-	c, err := newClient(name, endpoints, timeout, heartbeat)
-	if err != nil {
-		t.Fatal(err)
+	etcdConfig struct {
+		name      string
+		endpoints []string
+		timeout   time.Duration
+		heartbeat int
 	}
-	c.CleanKV()
-	return c
-}
-
-func TestMain(m *testing.M) {
 
-	startETCDServer()
-	m.Run()
-	stopETCDServer()
+	client *Client
 }
 
-func startETCDServer() {
+// start etcd server
+func (suite *ClientTestSuite) SetupSuite() {
 
 	cmd := exec.Command("./load.sh", "start")
 	cmd.Stdout = os.Stdout
 	cmd.Stderr = os.Stdout
 	cmd.Dir = "./single"
-
 	if err := cmd.Run(); err != nil {
-		panic(err)
+		suite.T().Fatal(err)
 	}
 }
 
-func stopETCDServer() {
+// stop etcd server
+func (suite *ClientTestSuite) TearDownSuite() {
+
 	cmd := exec.Command("./load.sh", "stop")
 	cmd.Stdout = os.Stdout
 	cmd.Stderr = os.Stdout
 	cmd.Dir = "./single"
-
 	if err := cmd.Run(); err != nil {
-		panic(err)
+		suite.T().Fatal(err)
 	}
+}
+
+func (suite *ClientTestSuite) setUpClient() *Client {
+	c, err := newClient(suite.etcdConfig.name,
+		suite.etcdConfig.endpoints,
+		suite.etcdConfig.timeout,
+		suite.etcdConfig.heartbeat)
+	if err != nil {
+		suite.T().Fatal(err)
+	}
+	return c
+}
 
+// set up a client for suite
+func (suite *ClientTestSuite) SetupTest() {
+	c := suite.setUpClient()
+	c.CleanKV()
+	suite.client = c
+	return
 }
 
-func Test_newClient(t *testing.T) {
+func (suite *ClientTestSuite) TestClientClose() {
 
-	c := initClient(t)
-	defer c.Close()
+	fmt.Println("called client close")
+
+	c := suite.client
+	t := suite.T()
 
+	defer c.Close()
 	if c.rawClient.ActiveConnection().GetState() != connectivity.Ready {
-		t.Fatal(c.rawClient.ActiveConnection().GetState())
+		t.Fatal(suite.client.rawClient.ActiveConnection().GetState())
 	}
 }
 
-func TestClient_Close(t *testing.T) {
+func (suite *ClientTestSuite) TestClientValid() {
+
+	fmt.Println("called client valid")
 
-	c := initClient(t)
+	c := suite.client
+	t := suite.T()
+
+	if c.Valid() != true {
+		t.Fatal("client is not valid")
+	}
 	c.Close()
+	if suite.client.Valid() != false {
+		t.Fatal("client is valid")
+	}
 }
 
-func TestClient_Create(t *testing.T) {
+func (suite *ClientTestSuite) TestClientDone() {
+
+	c := suite.client
+
+	go func() {
+		time.Sleep(2 * time.Second)
+		c.Close()
+	}()
+
+	c.Wait.Wait()
+}
+
+func (suite *ClientTestSuite) TestClientCreateKV() {
 
 	tests := tests
 
-	c := initClient(t)
-	defer c.Close()
+	c := suite.client
+	t := suite.T()
+
+	defer suite.client.Close()
 
 	for _, tc := range tests {
 
@@ -131,19 +168,18 @@ func TestClient_Create(t *testing.T) {
 		}
 
 		if value != expect {
-
 			t.Fatalf("expect %v but get %v", expect, value)
 		}
 
 	}
-
 }
 
-func TestClient_Delete(t *testing.T) {
+func (suite *ClientTestSuite) TestClientDeleteKV() {
 
 	tests := tests
+	c := suite.client
+	t := suite.T()
 
-	c := initClient(t)
 	defer c.Close()
 
 	for _, tc := range tests {
@@ -172,12 +208,12 @@ func TestClient_Delete(t *testing.T) {
 
 }
 
-func TestClient_GetChildrenKVList(t *testing.T) {
+func (suite *ClientTestSuite) TestClientGetChildrenKVList() {
 
 	tests := tests
 
-	c := initClient(t)
-	defer c.Close()
+	c := suite.client
+	t := suite.T()
 
 	var expectKList []string
 	var expectVList []string
@@ -210,12 +246,12 @@ func TestClient_GetChildrenKVList(t *testing.T) {
 
 }
 
-func TestClient_Watch(t *testing.T) {
+func (suite *ClientTestSuite) TestClientWatch() {
 
 	tests := tests
 
-	c := initClient(t)
-	defer c.Close()
+	c := suite.client
+	t := suite.T()
 
 	wg := sync.WaitGroup{}
 	wg.Add(1)
@@ -231,10 +267,6 @@ func TestClient_Watch(t *testing.T) {
 
 		for e := range wc {
 
-			if e.Err() != nil {
-				t.Fatal(err)
-			}
-
 			for _, event := range e.Events {
 				t.Logf("type IsCreate %v k %s v %s", event.IsCreate(), event.Kv.Key, event.Kv.Value)
 			}
@@ -262,10 +294,11 @@ func TestClient_Watch(t *testing.T) {
 
 }
 
-func TestClient_RegisterTemp(t *testing.T) {
+func (suite *ClientTestSuite) TestClientRegisterTemp() {
 
-	c := initClient(t)
-	observeC := initClient(t)
+	c := suite.client
+	observeC := suite.setUpClient()
+	t := suite.T()
 
 	wg := sync.WaitGroup{}
 	wg.Add(1)
@@ -281,9 +314,6 @@ func TestClient_RegisterTemp(t *testing.T) {
 
 			for _, event := range e.Events {
 
-				if e.Err() != nil {
-					t.Fatal(e.Err())
-				}
 				if event.Type == mvccpb.DELETE {
 					t.Logf("complete key (%s) is delete", completePath)
 					wg.Done()
@@ -306,32 +336,18 @@ func TestClient_RegisterTemp(t *testing.T) {
 	wg.Wait()
 }
 
-func TestClient_Valid(t *testing.T) {
-
-	c := initClient(t)
-
-	if c.Valid() != true {
-		t.Fatal("client is not valid")
-	}
-
-	c.Close()
-
-	if c.Valid() != false {
-
-		t.Fatal("client is valid")
-
-	}
-
-}
-
-func TestClient_Done(t *testing.T) {
-
-	c := initClient(t)
-
-	go func() {
-		time.Sleep(2 * time.Second)
-		c.Close()
-	}()
-
-	c.Wait.Wait()
+func TestClientSuite(t *testing.T) {
+	suite.Run(t, &ClientTestSuite{
+		etcdConfig: struct {
+			name      string
+			endpoints []string
+			timeout   time.Duration
+			heartbeat int
+		}{
+			name:      "test",
+			endpoints: []string{"localhost:2379"},
+			timeout:   time.Second,
+			heartbeat: 1,
+		},
+	})
 }
diff --git a/remoting/etcdv3/facede_test.go b/remoting/etcdv3/facede_test.go
index 590d30dc2fade430ce4d2f961e008faac8718042..94e9056c5990e210d1e7a70b09b42034cde326e4 100644
--- a/remoting/etcdv3/facede_test.go
+++ b/remoting/etcdv3/facede_test.go
@@ -3,7 +3,6 @@ package etcdv3
 import (
 	"context"
 	"sync"
-	"testing"
 	"time"
 
 	"github.com/apache/dubbo-go/common"
@@ -53,9 +52,10 @@ func (r *mockFacade) IsAvailable() bool {
 	return true
 }
 
-func Test_Fascade(t *testing.T) {
+func (suite *ClientTestSuite) TestFacade() {
 
-	c := initClient(t)
+	c := suite.client
+	t := suite.T()
 
 	url, err := common.NewURL(context.Background(), "mock://127.0.0.1:2379")
 	if err != nil {
diff --git a/remoting/etcdv3/listener_test.go b/remoting/etcdv3/listener_test.go
index 22f8b70889faee52e9d3ee5571f03a77a02446f7..648cf49fb990a6a63dacf8f8e7f40104f68fa7d8 100644
--- a/remoting/etcdv3/listener_test.go
+++ b/remoting/etcdv3/listener_test.go
@@ -1,7 +1,6 @@
 package etcdv3
 
 import (
-	"testing"
 	"time"
 
 	"github.com/apache/dubbo-go/remoting"
@@ -30,7 +29,7 @@ var changedData = `
 	dubbo.service.com.ikurento.user.UserProvider.cluster=failover
 `
 
-func TestListener(t *testing.T) {
+func (suite *ClientTestSuite) TestListener() {
 
 	var tests = []struct {
 		input struct {
@@ -44,8 +43,8 @@ func TestListener(t *testing.T) {
 		}{k: "/dubbo", v: changedData}},
 	}
 
-	c := initClient(t)
-	defer c.Close()
+	c := suite.client
+	t := suite.T()
 
 	listener := NewEventListener(c)
 	dataListener := &mockDataListener{client: c, changedData: changedData, rc: make(chan remoting.Event)}
@@ -64,7 +63,6 @@ func TestListener(t *testing.T) {
 	}
 	msg := <-dataListener.rc
 	assert.Equal(t, changedData, msg.Content)
-
 }
 
 type mockDataListener struct {
diff --git a/remoting/etcdv3/single/config.sh b/remoting/etcdv3/single/config.sh
index 0b2b9269580b58cee19f035f723ce8bb50c2aac9..a29762082bfc4793695110f89fc7f6db69199193 100755
--- a/remoting/etcdv3/single/config.sh
+++ b/remoting/etcdv3/single/config.sh
@@ -22,7 +22,7 @@ peer0_peer_port=2380
 
 export ETCDCTL_API=3
 etcd_endpoints="http://${peer0_ip}:${peer0_client_port}"
-ctl="./etcdctl --endpoints=$etcd_endpoints"
+ctl="etcdctl --endpoints=$etcd_endpoints"
 
 usage() {
     echo "Usage: $0 start"
@@ -34,7 +34,7 @@ usage() {
 }
 
 start() {
-    ./etcd --name=${name} \
+    etcd --name=${name} \
         --initial-advertise-peer-urls http://${!ip}:${!peer_port} \
         --listen-peer-urls http://${!ip}:${!peer_port} \
         --listen-client-urls http://${!ip}:${!client_port},http://127.0.0.1:${!client_port} \
@@ -43,7 +43,7 @@ start() {
         --initial-cluster etcd_node0=http://${peer0_ip}:${peer0_peer_port} \
         --initial-cluster-state new  >> ${log_dir}/${name}.log 2>&1 &
 
-    sleep 2
+    sleep 5
     PID=`ps aux | grep -w  "name=${name}" | grep ${!client_port} | grep -v grep | awk '{print $2}'`
     if [ "$PID" != "" ];
     then