go語言使用GoConvey框架進行測試

go語言使用GoConvey框架進行測試

本週作業爲在go-online上完成一個最小堆算法,在完成之後我使用GoConvey進行測試。

要想寫出好的的代碼,必須學會測試框架,對於golang,可以使用自帶的go test測試,也可以使用其他框架如

GoConvey,GoStub,GoMock,Monkey,本次我學習使用GoConvey。

安裝GoConvey

go get github.com/smartystreets/goconvey

需要等待較長的一段時間,然後查看$GOPATH/src/github.com目錄下增加了smartystreets文件夾即可。

使用GoConvey

將作業代碼複製到go工作空間中命名爲myheap.go,並且在同一目錄下創建myheap_test.go
在這裏插入圖片描述

go build或者go install生成包,不需main主函數。因爲要測試的函數需要有返回值,所以簡單修改一下作業中的函數,將nodes返回。

myheap_test.go文件如下:

package myheap

import (
    "testing"
    . "github.com/smartystreets/goconvey/convey"
)

func TestInit(t *testing.T) {
    Convey("test", t, func() {
		nodes := []Node{
			Node{3},
            Node{6},
            Node{9},
            Node{1},
            Node{2},
            Node{5},
            Node{8},
            Node{4},
            Node{7},
		}

		Convey("Test Init()", func(){
			So(Init(nodes), ShouldResemble, []Node{
				Node{1},
                Node{2},
                Node{5},
                Node{4},
                Node{3},
                Node{9},
                Node{8},
                Node{6},
                Node{7},
			})
        })

        nodes = Init(nodes)

        Convey("Test Push()", func(){
			So(Push(Node{0}, nodes), ShouldResemble, []Node{
				Node{0},
                Node{1},
                Node{5},
                Node{4},
                Node{2},
                Node{9},
                Node{8},
                Node{6},
                Node{7},
                Node{3},
			})
        })

        nodes = Push(Node{0}, nodes)

        Convey("Test Pop()", func(){
			So(Pop(nodes), ShouldResemble, []Node{
				Node{1},
				Node{2},
				Node{5},
				Node{4},
				Node{3},
				Node{9},
				Node{8},
				Node{6},
                Node{7},
			})
		})
	})
}

myheap.go文件如下:

package myheap

import "fmt"

type Node struct {
	Value int
}

// 用於構建結構體切片爲最小堆,需要調用down函數
func Init(nodes []Node)  []Node{
	for i := len(nodes)/2 - 1; i >= 0; i-- {
		down(nodes, i, len(nodes))
	}
	return nodes
}

// 需要down(下沉)的元素在切片中的索引爲i,n爲heap的長度,將該元素下沉到該元素對應的子樹合適的位置,從而滿足該子樹爲最小堆的要求
func down(nodes []Node, i, n int) {
	var parent int = i
	var child int = i*2+1
	var tmp int = nodes[i].Value
	for child < n {
		//取較小的孩子
		if (child < n-1) && (nodes[child].Value > nodes[child+1].Value) {
			child++
		}
		if tmp > nodes[child].Value {
			nodes[parent].Value = nodes[child].Value
			parent = child
			child = parent*2 + 1
		} else {
			break
		}
	}
	nodes[parent].Value = tmp
}

// 用於保證插入新元素(j爲元素的索引,切片末尾插入,堆底插入)的結構體切片之後仍然是一個最小堆
func up(nodes []Node, j int) {
	var child int = j
	var parent int = (j-1)/2
	var tmp int = nodes[j].Value
	for parent >= 0 && child >= 1 {
		if tmp < nodes[parent].Value {
			nodes[child].Value = nodes[parent].Value
			child = parent
			parent = (child-1)/2
		} else {
			break
		}
	}
	nodes[child].Value = tmp
}

// 彈出最小元素,並保證彈出後的結構體切片仍然是一個最小堆,第一個返回值是彈出的節點的信息,第二個參數是Pop操作後得到的新的結構體切片
func Pop(nodes []Node)  []Node {
	//min := nodes[0]
    nodes[0].Value = nodes[len(nodes)-1].Value
    nodes = nodes[ :len(nodes)-1]
    down(nodes,0,len(nodes)-1)
    return nodes
}

// 保證插入新元素時,結構體切片仍然是一個最小堆,需要調用up函數
func Push(node Node, nodes []Node) []Node {
	nodes = append(nodes, node)
    up(nodes, len(nodes)-1)
    return nodes
}

// 移除切片中指定索引的元素,保證移除後結構體切片仍然是一個最小堆
func Remove(nodes []Node, node Node) []Node {
	for i := 0; i < len(nodes); i++ {
        if node.Value == nodes[i].Value {
            nodes[i].Value = nodes[len(nodes)-1].Value
            nodes = nodes[:len(nodes)-1]
            down(nodes, i, len(nodes)-1)
        }
    }
    return nodes
}

//用於打印堆
func PrintList(nodes []Node) {
    for _, ele := range nodes {
        fmt.Printf("%d ", ele.Value)
    }
    fmt.Printf("\n")
}

進入該目錄並執行go test即可,與原生命令相同,然後可以看到輸出:

通過:

在這裏插入圖片描述

沒通過:

在這裏插入圖片描述
上面有具體信息
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章