作业2: TDD实践报告
实验环境
操作系统:Mac OS
编译器:VScode
迭代章节练习
练习1
- 修改测试代码,以便调用者可以指定字符重复的次数,然后修复代码
首先编写测试文件 repeat_test.go
代码和章节中给出的基本相同,只需要更改 Repeat()
函数中的参数为两个,一个是需要重复的字符串,另一个是重复的次数,代码如下
package iteration
import "testing"
func TestRepeat(t *testing.T) {
repeated := Repeat("a", 4 )
expected := "aaaaa"
if repeated != expected {
t.Errorf("expected '%q' but got '%q'", expected, repeated)
}
}
首先运行测试代码,得到如下的结果
可以看到由于未编写需要测试的函数,所以编译会失败
开始编写 Repeat()
函数,函数需要两个参数,一个是 string 类型,另一个是int 类型,实现的方法也是用了 for 循环的形式,代码如下
package iteration
func Repeat(character string, count int) string {
var ret string = ""
for i := 0; i < count; i++ {
ret += character
}
return ret
}
测试的代码写好后,可以直接在 VScode 中编译运行,或者在命令行中以 go test
命令进行测试,得到的结果如下所示
可以看到结果 FAIL
,原因是因为我在测试文件中选择了先测试 repeat 4次,所以得到的结果与期望的不一样,重新更改测试代码,便可以得到正确的结果,会显示 PASS
如下所示:
练习2
- 写一个
ExampleRepeat
来完善你的函数文档
关于示例的用法,在前一章节:整数中提到过,直接在 repeat_test.go
中创建新的函数 ExampleRepeat
,此函数用于输出得到的结果(注意:由于需要进行输出所以在代码开始处需要导入 fmt
包),与后面的注释中的内容进行比较,如果相同则成功,否则失败,代码如下:
func ExampleRepeat() {
s := Repeat("a", 5)
fmt.Println(s)
// Output: aaaa
}
反復を5回設定したことがわかります。以下のコメントの出力は4回繰り返されているため、以下に示すように、間違った結果が返されるはずです。
5回繰り返すように次のコメントを再修正します。テスト結果は次のとおりです。
結果からテストが成功したことがわかります PASS
演習3
- 見てください、文字列パッケージを。役立つと思われる関数を見つけ、それらのテストをいくつか記述します。標準ライブラリの学習に時間を費やすと、ゆっくりと成果が得られます。
func Compare(a, b string) int
関数、この関数は、前後の文字列の辞書サイズを比較するために使用され、a <bの場合は-1を返し、a = bの場合は0を返し、a> bの場合は1を返す、テストコードファイルはcompare_test.go
package iteration
import (
"strings"
"testing"
)
func TestCompare(t *testing.T) {
ans := strings.Compare("h", "z")
expected := -1
if ans != expected {
t.Errorf("expected '%d' but got '%d'", expected, ans)
}
}
次にテストすると、結果は次のようになります。
結果は、テストが成功したことを示しています
func Count(s, substr string) int
関数、この関数は、文字列sの部分文字列substrの数をカウントし、値を返します。テストコードファイルはcount_test.go
package iteration
import (
"strings"
"testing"
)
func TestCount(t *testing.T) {
ans := strings.Count("cheeze", "e")
expected := 3
if ans != expected {
t.Errorf("expected '%d' but got '%d'", expected, ans)
}
}
次にテストすると、結果は次のようになります。
結果からテストが成功したことがわかります
func ReplaceAll(s, old, new string) string
関数。この関数は、s文字列内のすべての古い文字列を新しい文字列に置き換えます。テストされたファイルはreplace_test.go
package iteration
import (
"strings"
"testing"
)
func TestReplace(t *testing.T) {
ans := strings.ReplaceAll("oink oink oink", "oink", "moo")
expected := "moo moo moo"
if ans != expected {
t.Errorf("expected '%s' but got '%s'", expected, ans)
}
}
次にテストすると、結果は次のようになります。
結果からテストが成功したことがわかります
高速ソートアルゴリズムの実装
アルゴリズムの紹介
クイックソート(Quicksort)は、バブルソートの改良版です。アルゴリズムの主な手順は次のとおりです。
まず境界値を設定し、境界値で配列を左右に分割します。
配列の右側のカットオフ値以上のデータと、配列の左側のカットオフ値未満のデータを収集します。このとき、左側の各要素はカットオフ値以下で、右側の各要素はカットオフ値以上です。
次に、左右のデータを個別にソートできます。左側の配列データの場合、境界値を使用して、データのこの部分を左と右の部分に分割し、小さい方の値を左側に、大きい方の値を右側に配置することもできます。右側の配列データも同様に処理できます。
上記のプロセスを繰り返すと、これが再帰的な定義であることがわかります。左側を再帰的にソートした後、右側を再帰的にソートします。左右のデータを並べ替えると、配列全体の並べ替えが完了します。
アルゴリズムの上記の説明を通じて、最初にメイン関数を完成させて、クイックソートが正常に実装されているかどうかをテストします。コードは次のとおりです。
package main
import "fmt"
const MAXN = 10
var arr = []int{
7, 4, 8, 5, 3, 6, 9, 1, 10, 2}
// 快速排序递归实现
func QuickSort(arr []int, l, r int) {
pivot := arr[l] // 选取中间值
pos := l // 中间值的位置
i, j := l, r
for i <= j {
for j >= pos && arr[j] >= pivot {
j--
}
if j >= pos {
arr[pos] = arr[j]
pos = j
}
for i <= pos && arr[i] <= pivot {
i++
}
if i <= pos {
arr[pos] = arr[i]
pos = i
}
}
arr[pos] = pivot
if pos-l > 1 {
QuickSort(arr, l, pos-1)
}
if r-pos > 1 {
QuickSort(arr, pos+1, r)
}
}
func main() {
QuickSort(arr, 0, len(arr)-1)
for i := 0; i < MAXN; i++ {
fmt.Printf("%d\t", arr[i])
}
}
コード全体を実行すると、次のように結果を確認できます。
最初にテストを書く
最初にテストファイルをQuickSort_test.go
書き込みQuickSort.go
ますが、テストファイルが出力されるかどうかを確認するためにファイルを書き込みません
package Qsort
import "testing"
const MAXN = 10
var arr = []int{
7, 4, 8, 5, 3, 6, 9, 1, 10, 2}
func TestQuickSort(t *testing.T) {
QuickSort(arr, 0, MAXN-1)
expected := []int{
1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
flag := true
for i := 0; i < MAXN; i++ {
if arr[i] != expected[i] {
flag = false
}
}
if flag == false {
t.Errorf("expected ")
for i := 0; i < MAXN; i++ {
t.Errorf("%d\t", expected[i])
}
t.Errorf("but got")
for i := 0; i < MAXN; i++ {
t.Errorf("%d\t", arr[i])
}
}
}
コードを記述したら、直接実行して次の結果を取得します
テストされたファイルがないため、コンパイルエラーが発生することがわかります
最小限のコード実行テスト
QuickSort.go
テストを正常に実行できるように、テストするコードファイルの記述を開始します。正しい構文で空のコードを記述してください。
package Qsort
// 快速排序递归实现
func QuickSort(arr []int, l, r int) {
}
コードを記述した後、テストすると、出力結果は次のようになります
成功したコード完了テスト
事前テストが終了しQuickSort.go
たら、ファイルを変更し、変更されたコードは
package Qsort
// 快速排序递归实现
func QuickSort(arr []int, l, r int) {
pivot := arr[l] // 选取中间值
pos := l // 中间值的位置
i, j := l, r
for i <= j {
for j >= pos && arr[j] >= pivot {
j--
}
if j >= pos {
arr[pos] = arr[j]
pos = j
}
for i <= pos && arr[i] <= pivot {
i++
}
if i <= pos {
arr[pos] = arr[i]
pos = i
}
}
arr[pos] = pivot
if pos-l > 1 {
QuickSort(arr, l, pos-1)
}
if r-pos > 1 {
QuickSort(arr, pos+1, r)
}
}
最初のテスト、テストコードで予期される2を3に変更して、テストファイルがエラーを検出できるかどうかを確認します。結果は図に示されています
上の図から、テストファイルがエラーを検出して正しいテストを実行できることがわかります。結果は
上図のようになります。テストが成功し、成功したことがわかります。これは、設計したクイックソートコードが正しいことを示しています。
リファクタリング
元のアルゴリズムは変更する必要がほとんどないため、元のコードの上にコメントが付けられます
ベンチマーク
テストファイルにベンチマークテストを記述し、テストコードをbN回実行し、所要時間をテストします。追加したコードは次のとおりです。
func BenchmarkQuickSort(b *testing.B) {
for i := 0; i < b.N; i++ {
var arrt = []int{
7, 4, 8, 5, 3, 6, 9, 1, 10, 2}
QuickSort(arrt, 0, MAXN-1)
}
}
コードのベンチマークを行った後、コマンドラインにコマンドを入力しgo test -bench=.
、テストコードを実行する時間を入力すると、結果は次のようになります。
これまでのところ、テストプロセス全体が完了しています
githubアドレス
コードポータル:ポータル
総括する
この実験を通して、私はテストの基本的なステップを学び、TDD、リファクタリング、テスト、ベンチマークテストなどの概念を理解し、さらにGO言語のいくつかの使用法を習得しました。コードの記述やコードの記述で巧みに使用できます。また、C言語学習ネットワークでのGO の学習を通じて解決されたいくつかの問題にも直面しました。