Merge pull request #158 from hantmac/develop

modify unit test to use mock
This commit is contained in:
Marvin Zhang
2019-08-22 17:39:19 +08:00
committed by GitHub
11 changed files with 609 additions and 42 deletions

16
backend/mock/base.go Normal file
View File

@@ -0,0 +1,16 @@
package mock
type Response struct {
Status string `json:"status"`
Message string `json:"message"`
Data interface{} `json:"data"`
Error string `json:"error"`
}
type ListResponse struct {
Status string `json:"status"`
Message string `json:"message"`
Total int `json:"total"`
Data interface{} `json:"data"`
Error string `json:"error"`
}

8
backend/mock/file.go Normal file
View File

@@ -0,0 +1,8 @@
package mock
type File struct {
Name string `json:"name"`
Path string `json:"path"`
IsDir bool `json:"is_dir"`
Size int64 `json:"size"`
}

210
backend/mock/node.go Normal file
View File

@@ -0,0 +1,210 @@
package mock
import (
"crawlab/model"
"crawlab/services"
"github.com/apex/log"
"github.com/gin-gonic/gin"
"github.com/globalsign/mgo/bson"
"net/http"
"time"
)
var NodeList = []model.Node{
{
Id: bson.ObjectId("5d429e6c19f7abede924fee2"),
Ip: "10.32.35.15",
Name: "test1",
Status: "online",
Port: "8081",
Mac: "ac:12:df:12:fd",
Description: "For test1",
IsMaster: true,
UpdateTs: time.Now(),
CreateTs: time.Now(),
UpdateTsUnix: time.Now().Unix(),
},
{
Id: bson.ObjectId("5d429e6c19f7abede924fe22"),
Ip: "10.32.35.12",
Name: "test2",
Status: "online",
Port: "8082",
Mac: "ac:12:df:12:vh",
Description: "For test2",
IsMaster: true,
UpdateTs: time.Now(),
CreateTs: time.Now(),
UpdateTsUnix: time.Now().Unix(),
},
}
var TaskList = []model.Task{
{
Id: "1234",
SpiderId: bson.ObjectId("xx429e6c19f7abede924fee2"),
StartTs: time.Now(),
FinishTs: time.Now(),
Status: "进行中",
NodeId: bson.ObjectId("5d429e6c19f7abede924fee2"),
LogPath: "./log",
Cmd: "scrapy crawl test",
Error: "",
ResultCount: 0,
WaitDuration: 10.0,
RuntimeDuration: 10,
TotalDuration: 20,
SpiderName: "test",
NodeName: "test",
CreateTs: time.Now(),
UpdateTs: time.Now(),
},
{
Id: "5678",
SpiderId: bson.ObjectId("xx429e6c19f7abede924fddf"),
StartTs: time.Now(),
FinishTs: time.Now(),
Status: "进行中",
NodeId: bson.ObjectId("5d429e6c19f7abede924fee2"),
LogPath: "./log",
Cmd: "scrapy crawl test2",
Error: "",
ResultCount: 0,
WaitDuration: 10.0,
RuntimeDuration: 10,
TotalDuration: 20,
SpiderName: "test",
NodeName: "test",
CreateTs: time.Now(),
UpdateTs: time.Now(),
},
}
var dataList = []services.Data{
{
Mac: "ac:12:fc:fd:ds:dd",
Ip: "192.10.2.1",
Master: true,
UpdateTs: time.Now(),
UpdateTsUnix: time.Now().Unix(),
},
{
Mac: "22:12:fc:fd:ds:dd",
Ip: "182.10.2.2",
Master: true,
UpdateTs: time.Now(),
UpdateTsUnix: time.Now().Unix(),
},
}
var executeble = []model.Executable{
{
Path: "/test",
FileName: "test.py",
DisplayName: "test.py",
},
}
var systemInfo = model.SystemInfo{ARCH: "x86",
OS: "linux",
Hostname: "test",
NumCpu: 4,
Executables: executeble,
}
func GetNodeList(c *gin.Context) {
nodes := NodeList
c.JSON(http.StatusOK, Response{
Status: "ok",
Message: "success",
Data: nodes,
})
}
func GetNode(c *gin.Context) {
var result model.Node
id := c.Param("id")
for _, node := range NodeList {
if node.Id == bson.ObjectId(id) {
result = node
}
}
c.JSON(http.StatusOK, Response{
Status: "ok",
Message: "success",
Data: result,
})
}
func Ping(c *gin.Context) {
data := dataList[0]
c.JSON(http.StatusOK, Response{
Status: "ok",
Message: "success",
Data: data,
})
}
func PostNode(c *gin.Context) {
id := c.Param("id")
var oldItem model.Node
for _, node := range NodeList {
if node.Id == bson.ObjectId(id) {
oldItem = node
}
}
log.Info(id)
var newItem model.Node
if err := c.ShouldBindJSON(&newItem); err != nil {
HandleError(http.StatusBadRequest, c, err)
return
}
newItem.Id = oldItem.Id
log.Info("Post Node success")
c.JSON(http.StatusOK, Response{
Status: "ok",
Message: "success",
})
}
func GetNodeTaskList(c *gin.Context) {
tasks := TaskList
c.JSON(http.StatusOK, Response{
Status: "ok",
Message: "success",
Data: tasks,
})
}
func DeleteNode(c *gin.Context) {
id := bson.ObjectId("5d429e6c19f7abede924fee2")
for _, node := range NodeList {
if node.Id == bson.ObjectId(id) {
log.Infof("Delete a node")
}
}
c.JSON(http.StatusOK, Response{
Status: "ok",
Message: "success",
})
}
func GetSystemInfo(c *gin.Context) {
id := c.Param("id")
log.Info(id)
sysInfo := systemInfo
c.JSON(http.StatusOK, Response{
Status: "ok",
Message: "success",
Data: sysInfo,
})
}

View File

@@ -1,17 +1,17 @@
package routes
package mock
import (
"crawlab/config"
"crawlab/database"
"crawlab/model"
"encoding/json"
"github.com/apex/log"
"github.com/gin-gonic/gin"
"github.com/globalsign/mgo/bson"
. "github.com/smartystreets/goconvey/convey"
"github.com/spf13/viper"
"net/http"
"net/http/httptest"
"runtime/debug"
"strings"
"testing"
"time"
"ucloudBilling/ucloud/log"
)
var app *gin.Engine
@@ -19,34 +19,7 @@ var app *gin.Engine
func init() {
app = gin.Default()
// 初始化配置
if err := config.InitConfig("../conf/config.yml"); err != nil {
panic(err)
}
log.Info("初始化配置成功")
// 初始化日志设置
logLevel := viper.GetString("log.level")
if logLevel != "" {
log.SetLevelFromString(logLevel)
}
log.Info("初始化日志设置成功")
// 初始化Mongodb数据库
if err := database.InitMongo(); err != nil {
debug.PrintStack()
panic(err)
}
log.Info("初始化Mongodb数据库成功")
// 初始化Redis数据库
if err := database.InitRedis(); err != nil {
debug.PrintStack()
panic(err)
}
log.Info("初始化Redis数据库成功")
// 路由
// mock Test
// 节点相关的API
app.GET("/ping", Ping)
app.GET("/nodes", GetNodeList) // 节点列表
@@ -55,20 +28,27 @@ func init() {
app.GET("/nodes/:id/tasks", GetNodeTaskList) // 节点任务列表
app.GET("/nodes/:id/system", GetSystemInfo) // 节点任务列表
app.DELETE("/nodes/:id", DeleteNode) // 删除节点
// 爬虫
//// 爬虫
// 定时任务
app.GET("/schedules", GetScheduleList) // 定时任务列表
app.GET("/schedules/:id", GetSchedule) // 定时任务详情
app.PUT("/schedules", PutSchedule) // 创建定时任务
app.POST("/schedules/:id", PostSchedule) // 修改定时任务
app.DELETE("/schedules/:id", DeleteSchedule) // 删除定时任务
}
//先测试GetNodeList得到一个节点的ID再继续测试下面的API
//mock test, test data in ./mock
func TestGetNodeList(t *testing.T) {
var resp Response
w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/nodes", nil)
app.ServeHTTP(w, req)
err := json.Unmarshal([]byte(w.Body.String()), &resp)
t.Log(resp.Data)
if err != nil {
t.Fatal("Unmarshal resp failed")
}
t.Log(resp.Data)
Convey("Test API GetNodeList", t, func() {
Convey("Test response status", func() {
So(resp.Status, ShouldEqual, "ok")
@@ -77,10 +57,9 @@ func TestGetNodeList(t *testing.T) {
})
}
//依赖MongoDB中的数据,_id=5d429e6c19f7abede924fee2,实际测试时需替换
func TestGetNode(t *testing.T) {
var resp Response
var mongoId = "5d5a658319f7ab423585b0b0"
var mongoId = "5d429e6c19f7abede924fee2"
w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/nodes/"+mongoId, nil)
app.ServeHTTP(w, req)
@@ -93,7 +72,7 @@ func TestGetNode(t *testing.T) {
Convey("Test response status", func() {
So(resp.Status, ShouldEqual, "ok")
So(resp.Message, ShouldEqual, "success")
So(resp.Data.(map[string]interface{})["_id"], ShouldEqual, mongoId)
So(resp.Data.(map[string]interface{})["_id"], ShouldEqual, bson.ObjectId(mongoId).Hex())
})
})
}
@@ -117,7 +96,7 @@ func TestPing(t *testing.T) {
func TestGetNodeTaskList(t *testing.T) {
var resp Response
var mongoId = "5d5a658319f7ab423585b0b0"
var mongoId = "5d429e6c19f7abede924fee2"
w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "nodes/"+mongoId+"/tasks", nil)
app.ServeHTTP(w, req)
@@ -135,7 +114,8 @@ func TestGetNodeTaskList(t *testing.T) {
func TestDeleteNode(t *testing.T) {
var resp Response
var mongoId = "5d5a658319f7ab423585b0b0"
var mongoId = "5d429e6c19f7abede924fee2"
w := httptest.NewRecorder()
req, _ := http.NewRequest("DELETE", "nodes/"+mongoId, nil)
app.ServeHTTP(w, req)
@@ -150,3 +130,58 @@ func TestDeleteNode(t *testing.T) {
})
})
}
func TestPostNode(t *testing.T) {
var newItem = model.Node{
Id: bson.ObjectIdHex("5d429e6c19f7abede924fee2"),
Ip: "10.32.35.15",
Name: "test1",
Status: "online",
Port: "8081",
Mac: "ac:12:df:12:fd",
Description: "For test1",
IsMaster: true,
UpdateTs: time.Now(),
CreateTs: time.Now(),
UpdateTsUnix: time.Now().Unix(),
}
var resp Response
body, _ := json.Marshal(newItem)
log.Info(strings.NewReader(string(body)))
var mongoId = "5d429e6c19f7abede924fee2"
w := httptest.NewRecorder()
req, _ := http.NewRequest("POST", "nodes/"+mongoId, strings.NewReader(string(body)))
app.ServeHTTP(w, req)
err := json.Unmarshal([]byte(w.Body.String()), &resp)
t.Log(resp)
if err != nil {
t.Fatal("Unmarshal resp failed")
}
Convey("Test API PostNode", t, func() {
Convey("Test response status", func() {
So(resp.Status, ShouldEqual, "ok")
So(resp.Message, ShouldEqual, "success")
})
})
}
func TestGetSystemInfo(t *testing.T) {
var resp Response
var mongoId = "5d429e6c19f7abede924fee2"
w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "nodes/"+mongoId+"/system", nil)
app.ServeHTTP(w, req)
err := json.Unmarshal([]byte(w.Body.String()), &resp)
if err != nil {
t.Fatal("Unmarshal resp failed")
}
Convey("Test API GetSystemInfo", t, func() {
Convey("Test response status", func() {
So(resp.Status, ShouldEqual, "ok")
So(resp.Message, ShouldEqual, "success")
})
})
}

126
backend/mock/schedule.go Normal file
View File

@@ -0,0 +1,126 @@
package mock
import (
"crawlab/constants"
"crawlab/model"
"fmt"
"github.com/gin-gonic/gin"
"github.com/globalsign/mgo/bson"
"net/http"
"time"
)
var scheduleList = []model.Schedule{
{
Id: bson.ObjectId("5d429e6c19f7abede924fee2"),
Name: "test schedule",
SpiderId: "123",
NodeId: bson.ObjectId("5d429e6c19f7abede924fee2"),
Cron: "***1*",
EntryId: 10,
// 前端展示
SpiderName: "test scedule",
NodeName: "测试节点",
CreateTs: time.Now(),
UpdateTs: time.Now(),
},
{
Id: bson.ObjectId("xx429e6c19f7abede924fee2"),
Name: "test schedule2",
SpiderId: "234",
NodeId: bson.ObjectId("5d429e6c19f7abede924fee2"),
Cron: "***1*",
EntryId: 10,
// 前端展示
SpiderName: "test scedule2",
NodeName: "测试节点",
CreateTs: time.Now(),
UpdateTs: time.Now(),
},
}
func GetScheduleList(c *gin.Context) {
results := scheduleList
c.JSON(http.StatusOK, Response{
Status: "ok",
Message: "success",
Data: results,
})
}
func GetSchedule(c *gin.Context) {
id := c.Param("id")
var result model.Schedule
for _, sch := range scheduleList {
if sch.Id == bson.ObjectId(id) {
result = sch
}
}
c.JSON(http.StatusOK, Response{
Status: "ok",
Message: "success",
Data: result,
})
}
func PostSchedule(c *gin.Context) {
id := c.Param("id")
var oldItem model.Schedule
for _, sch := range scheduleList {
if sch.Id == bson.ObjectId(id) {
oldItem = sch
}
}
var newItem model.Schedule
if err := c.ShouldBindJSON(&newItem); err != nil {
HandleError(http.StatusBadRequest, c, err)
return
}
newItem.Id = oldItem.Id
c.JSON(http.StatusOK, Response{
Status: "ok",
Message: "success",
})
}
func PutSchedule(c *gin.Context) {
var item model.Schedule
// 绑定数据模型
if err := c.ShouldBindJSON(&item); err != nil {
HandleError(http.StatusBadRequest, c, err)
return
}
// 如果node_id为空则置为空ObjectId
if item.NodeId == "" {
item.NodeId = bson.ObjectIdHex(constants.ObjectIdNull)
}
c.JSON(http.StatusOK, Response{
Status: "ok",
Message: "success",
})
}
func DeleteSchedule(c *gin.Context) {
id := bson.ObjectIdHex("5d429e6c19f7abede924fee2")
for _, sch := range scheduleList {
if sch.Id == bson.ObjectId(id) {
fmt.Println("delete a schedule")
}
}
fmt.Println(id)
fmt.Println("update schedule")
c.JSON(http.StatusOK, Response{
Status: "ok",
Message: "success",
})
}

View File

@@ -0,0 +1,144 @@
package mock
import (
"crawlab/model"
"encoding/json"
"github.com/globalsign/mgo/bson"
. "github.com/smartystreets/goconvey/convey"
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"
"ucloudBilling/ucloud/log"
)
func TestGetScheduleList(t *testing.T) {
var resp Response
w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/schedules", nil)
app.ServeHTTP(w, req)
err := json.Unmarshal([]byte(w.Body.String()), &resp)
if err != nil {
t.Fatal("Unmarshal resp failed")
}
t.Log(resp.Data)
Convey("Test API GetScheduleList", t, func() {
Convey("Test response status", func() {
So(resp.Status, ShouldEqual, "ok")
So(resp.Message, ShouldEqual, "success")
})
})
}
func TestGetSchedule(t *testing.T) {
var mongoId = "5d429e6c19f7abede924fee2"
var resp Response
w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/schedules/"+mongoId, nil)
app.ServeHTTP(w, req)
err := json.Unmarshal([]byte(w.Body.String()), &resp)
if err != nil {
t.Fatal("Unmarshal resp failed")
}
Convey("Test API GetSchedule", t, func() {
Convey("Test response status", func() {
So(resp.Status, ShouldEqual, "ok")
So(resp.Message, ShouldEqual, "success")
So(resp.Data.(map[string]interface{})["_id"], ShouldEqual, bson.ObjectId(mongoId).Hex())
})
})
}
func TestDeleteSchedule(t *testing.T) {
var mongoId = "5d429e6c19f7abede924fee2"
var resp Response
w := httptest.NewRecorder()
req, _ := http.NewRequest("DELETE", "/schedules/"+mongoId, nil)
app.ServeHTTP(w, req)
err := json.Unmarshal([]byte(w.Body.String()), &resp)
log.Info(w.Body.String())
if err != nil {
t.Fatal("Unmarshal resp failed")
}
Convey("Test DeleteSchedule", t, func() {
Convey("Test resp status", func() {
So(resp.Status, ShouldEqual, "ok")
})
})
}
func TestPostSchedule(t *testing.T) {
var newItem = model.Schedule{
Id: bson.ObjectIdHex("5d429e6c19f7abede924fee2"),
Name: "test schedule",
SpiderId: bson.ObjectIdHex("5d429e6c19f7abede924fee2"),
NodeId: bson.ObjectIdHex("5d429e6c19f7abede924fee2"),
Cron: "***1*",
EntryId: 10,
// 前端展示
SpiderName: "test scedule",
NodeName: "测试节点",
CreateTs: time.Now(),
UpdateTs: time.Now(),
}
var resp Response
var mongoId = "5d429e6c19f7abede924fee2"
body,_ := json.Marshal(newItem)
log.Info(strings.NewReader(string(body)))
w := httptest.NewRecorder()
req,_ := http.NewRequest("POST", "/schedules/"+mongoId,strings.NewReader(string(body)))
app.ServeHTTP(w, req)
err := json.Unmarshal([]byte(w.Body.String()),&resp)
t.Log(resp)
if err != nil {
t.Fatal("unmarshal resp failed")
}
Convey("Test API PostSchedule", t, func() {
Convey("Test response status", func() {
So(resp.Status, ShouldEqual, "ok")
So(resp.Message, ShouldEqual, "success")
})
})
}
func TestPutSchedule(t *testing.T) {
var newItem = model.Schedule{
Id: bson.ObjectIdHex("5d429e6c19f7abede924fee2"),
Name: "test schedule",
SpiderId: bson.ObjectIdHex("5d429e6c19f7abede924fee2"),
NodeId: bson.ObjectIdHex("5d429e6c19f7abede924fee2"),
Cron: "***1*",
EntryId: 10,
// 前端展示
SpiderName: "test scedule",
NodeName: "测试节点",
CreateTs: time.Now(),
UpdateTs: time.Now(),
}
var resp Response
body,_ := json.Marshal(newItem)
log.Info(strings.NewReader(string(body)))
w := httptest.NewRecorder()
req,_ := http.NewRequest("PUT", "/schedules",strings.NewReader(string(body)))
app.ServeHTTP(w, req)
err := json.Unmarshal([]byte(w.Body.String()),&resp)
t.Log(resp)
if err != nil {
t.Fatal("unmarshal resp failed")
}
Convey("Test API PutSchedule", t, func() {
Convey("Test response status", func() {
So(resp.Status, ShouldEqual, "ok")
So(resp.Message, ShouldEqual, "success")
})
})
}

1
backend/mock/spider.go Normal file
View File

@@ -0,0 +1 @@
package mock

1
backend/mock/system.go Normal file
View File

@@ -0,0 +1 @@
package mock

1
backend/mock/task.go Normal file
View File

@@ -0,0 +1 @@
package mock

1
backend/mock/user.go Normal file
View File

@@ -0,0 +1 @@
package mock

24
backend/mock/utils.go Normal file
View File

@@ -0,0 +1,24 @@
package mock
import (
"github.com/gin-gonic/gin"
"runtime/debug"
)
func HandleError(statusCode int, c *gin.Context, err error) {
debug.PrintStack()
c.JSON(statusCode, Response{
Status: "ok",
Message: "error",
Error: err.Error(),
})
}
func HandleErrorF(statusCode int, c *gin.Context, err string) {
debug.PrintStack()
c.JSON(statusCode, Response{
Status: "ok",
Message: "error",
Error: err,
})
}