130 lines
3.5 KiB
Go
130 lines
3.5 KiB
Go
|
package strategy
|
|||
|
|
|||
|
import (
|
|||
|
"github.com/shopspring/decimal"
|
|||
|
"reflect"
|
|||
|
"testing"
|
|||
|
)
|
|||
|
|
|||
|
// --- 表格式驅動測試 (Table-Driven Test) ---
|
|||
|
|
|||
|
func TestRingQD(t *testing.T) {
|
|||
|
// 為了方便測試,預先建立幾個 decimal 數值
|
|||
|
d10 := decimal.NewFromInt(10)
|
|||
|
d20 := decimal.NewFromInt(20)
|
|||
|
d30 := decimal.NewFromInt(30)
|
|||
|
d40 := decimal.NewFromInt(40)
|
|||
|
d50 := decimal.NewFromInt(50)
|
|||
|
d_neg5 := decimal.NewFromInt(-5)
|
|||
|
|
|||
|
// 定義測試案例的結構
|
|||
|
testCases := []struct {
|
|||
|
name string // 測試案例的名稱
|
|||
|
n int // ringQD 的大小
|
|||
|
inputs []decimal.Decimal // 輸入的數值序列
|
|||
|
wantSum decimal.Decimal // 預期的總和
|
|||
|
wantMean decimal.Decimal // 預期的平均值
|
|||
|
wantValues []decimal.Decimal // 預期隊列中最後的值
|
|||
|
wantReady bool // 預期的就緒狀態
|
|||
|
}{
|
|||
|
{
|
|||
|
name: "未滿載的情況",
|
|||
|
n: 5,
|
|||
|
inputs: []decimal.Decimal{d10, d20},
|
|||
|
wantSum: decimal.NewFromInt(30),
|
|||
|
wantMean: decimal.NewFromInt(15),
|
|||
|
wantValues: []decimal.Decimal{d10, d20},
|
|||
|
wantReady: false,
|
|||
|
},
|
|||
|
{
|
|||
|
name: "剛好滿載的情況",
|
|||
|
n: 3,
|
|||
|
inputs: []decimal.Decimal{d10, d20, d30},
|
|||
|
wantSum: decimal.NewFromInt(60),
|
|||
|
wantMean: decimal.NewFromInt(20),
|
|||
|
wantValues: []decimal.Decimal{d10, d20, d30},
|
|||
|
wantReady: true,
|
|||
|
},
|
|||
|
{
|
|||
|
name: "超出容量,舊資料被移除",
|
|||
|
n: 3,
|
|||
|
inputs: []decimal.Decimal{d10, d20, d30, d40, d50},
|
|||
|
wantSum: decimal.NewFromInt(120), // 30 + 40 + 50
|
|||
|
wantMean: decimal.NewFromInt(40),
|
|||
|
wantValues: []decimal.Decimal{d30, d40, d50},
|
|||
|
wantReady: true,
|
|||
|
},
|
|||
|
{
|
|||
|
name: "包含零與負數",
|
|||
|
n: 4,
|
|||
|
inputs: []decimal.Decimal{d10, d_neg5, decimal.Zero, d30, d_neg5},
|
|||
|
wantSum: decimal.NewFromInt(20), // -5 + 0 + 30 + (-5)
|
|||
|
wantMean: decimal.NewFromInt(5),
|
|||
|
wantValues: []decimal.Decimal{d_neg5, decimal.Zero, d30, d_neg5},
|
|||
|
wantReady: true,
|
|||
|
},
|
|||
|
{
|
|||
|
name: "初始為空",
|
|||
|
n: 5,
|
|||
|
inputs: []decimal.Decimal{},
|
|||
|
wantSum: decimal.Zero,
|
|||
|
wantMean: decimal.Zero,
|
|||
|
wantValues: []decimal.Decimal{},
|
|||
|
wantReady: false,
|
|||
|
},
|
|||
|
{
|
|||
|
name: "N 為 1 的邊界情況",
|
|||
|
n: 1,
|
|||
|
inputs: []decimal.Decimal{d10, d20, d30},
|
|||
|
wantSum: d30,
|
|||
|
wantMean: d30,
|
|||
|
wantValues: []decimal.Decimal{d30},
|
|||
|
wantReady: true,
|
|||
|
},
|
|||
|
{
|
|||
|
name: "N 為 0 的無效情況",
|
|||
|
n: 0,
|
|||
|
inputs: []decimal.Decimal{d10, d20, d30},
|
|||
|
wantSum: decimal.Zero,
|
|||
|
wantMean: decimal.Zero,
|
|||
|
wantValues: []decimal.Decimal{},
|
|||
|
wantReady: true,
|
|||
|
},
|
|||
|
}
|
|||
|
|
|||
|
// 遍歷所有測試案例
|
|||
|
for _, tc := range testCases {
|
|||
|
t.Run(tc.name, func(t *testing.T) {
|
|||
|
// 針對每個案例建立一個新的 ringQD
|
|||
|
q := newRingQD(tc.n)
|
|||
|
|
|||
|
// 依序推入資料
|
|||
|
for _, val := range tc.inputs {
|
|||
|
q.push(val)
|
|||
|
}
|
|||
|
|
|||
|
// 驗證總和
|
|||
|
if !q.sum.Equals(tc.wantSum) {
|
|||
|
t.Errorf("Sum 錯誤:got %v, want %v", q.sum, tc.wantSum)
|
|||
|
}
|
|||
|
|
|||
|
// 驗證平均值
|
|||
|
gotMean := q.mean()
|
|||
|
if !gotMean.Equals(tc.wantMean) {
|
|||
|
t.Errorf("Mean 錯誤:got %v, want %v", gotMean, tc.wantMean)
|
|||
|
}
|
|||
|
|
|||
|
// 驗證就緒狀態
|
|||
|
if q.ready() != tc.wantReady {
|
|||
|
t.Errorf("Ready 狀態錯誤:got %v, want %v", q.ready(), tc.wantReady)
|
|||
|
}
|
|||
|
|
|||
|
// 驗證隊列中的值
|
|||
|
gotValues := q.values()
|
|||
|
if !reflect.DeepEqual(gotValues, tc.wantValues) {
|
|||
|
t.Errorf("Values 錯誤:got %v, want %v", gotValues, tc.wantValues)
|
|||
|
}
|
|||
|
})
|
|||
|
}
|
|||
|
}
|