D
Daria’s room
@dariasroom737 подп.
1.2Kпросмотров
29 ноября 2025 г.
Score: 1.3K
Сегодня открыла для себя fuzzy тесты, которые уже оказывается много лет существуют наряду с unit и benchmark тестами. А назначение у них как раз автоматически прогонять через функцию кучу разнообразных входных данных, включая редкие и нетипичные варианты (пустые длинные/короткие строки, NaN, битые unicode символы, спец байты и тд). В моем проекте сейчас, который касается расчета цен и скидок, важно учесть все нетривиальные случаи, поэтому fuzzy тесты зашли на ура. Базово работа с fuzz тестом выглядит так: func FuzzParseInt(f testing.F) { // На входе указываем seeds для генерации входных данных f.Add(1000.0, 5, 10, true) f.Add(100.0, 0, 0, false) f.Add(9999.0, 25, 50, true) f.Add(1.0, 0, 50, true) f.Add(5000.0, 10, 25, false) // На 1 fuzz тест должен быть 1 fuzz target = функция, которую тестируем f.Fuzz(func(t testing.T, baseF float64, baseDiscount, publicDiscount int, withPublicDiscount bool) { base := decimal.NewFromFloat(baseF) input := []PriceWithDiscount{ { ID: "FUZZID", BasePrice: base, Currency: "RUB", BaseDiscountPercent: baseDiscount, PublicDiscountPercent: publicDiscount, HasPublicDiscount: withPublicDiscount, }, } calc := NewCalculator(CountryRU).CalcPrice(input) got := calc[input[0].ID] init, _ := decimal.NewFromString(got.InitialPrice) final, _ := decimal.NewFromString(got.FinalPrice) // По бизнес логике итоговая цена не может быть выше начальной if final.GreaterThan(init) { t.Fatalf("FinalPrice > InitialPrice: %s > %s", final, init) } // Считаем сумму всех скидок sum := decimal.Zero for _, d := range got.Discounts { acc, _ := decimal.NewFromString(d.AmountAccumulated) if acc.GreaterThan(init) { t.Fatalf("AmountAccumulated > InitialPrice: %s > %s", acc, init) } a, _ := decimal.NewFromString(d.Amount) sum = sum.Add(a) } diff := init.Sub(final).Sub(sum).Abs() // Разница до 1 рубля при ожидаема, допускаем ее if diff.GreaterThan(decimal.NewFromFloat(1)) { t.Fatalf("FinalPrice mismatch: final=%s expected=%s diff=%s", final, init.Sub(sum), diff) } }) } Итак, стартовый набор (seed corpus) мы задали через Add, дальше их будут мутировать и использовать для вызовов Затем запускаем фаззинг с go test -fuzz=FuzzCalcPrice -fuzztime=30s. Время - без ограничений, в теории может крутится сколько угодно, если ни один тест не валится. Обычно запускается сразу конкурентно на N горутин для производительности, также пишет количество выполненных итераций на 1 секунду и общее число вызовов fuzz: elapsed: 27s, execs: 4704975 (175480/sec), new interesting: 28 (total: 292) fuzz: elapsed: 30s, execs: 5196168 (163772/sec), new interesting: 29 (total: 293) fuzz: elapsed: 30s, execs: 5196168 (0/sec), new interesting: 29 (total: 293)
1.2K
просмотров
2935
символов
Нет
эмодзи
Нет
медиа

Другие посты @dariasroom

Все посты канала →
Сегодня открыла для себя fuzzy тесты, которые уже оказываетс — @dariasroom | PostSniper