Deutsch
Germany.ruФорумы → Архив Досок→ Программирование

NUnit - TDD - математическая формула

1583  1 2 3 4 все
alex445 старожил16.10.21 19:08
16.10.21 19:08 
Последний раз изменено 16.10.21 19:35 (alex445)

Если TDD, то вроде сначала в тестах описываем бизнес логику, а потом пишем код, чтобы тестам удовлетворяли? Если так, то бизнес-логика такая:


1) к целочисленным значениям должно применяться целое или равное 0 число процентов - т.е. из целого числа может получиться дробное;


2) при применении отрицательного числа процентов число должно уменьшаться, при этом -100% означает обнуление числа, и дальнейшее снижение процентов должно приводить всё к тому же обнулению;


3) результат должен округляться по математическим правилам до целого - т.е. при ,5 в бОльшую сторону, при -,5 - в меньшую - т.е. away from zero.


Вроде, это диктует правило, что в реализации логики нужно при применении процентов перейти к числам с плавающей запятой, а потом округлить по указанным правилам. Но я сейчас говорю о тесте. Как для такой задачи написать тест? У меня получилось только так - очень много условий (пытался проверить граничные значения процентов - как получившееся число с пятью десятыми или близко к этому будет округляться). Значения считал на калькуляторе, арифметические действия языка не использовал.


Вопрос - можно ли принципиально проще и короче (т.е. не просто несколько кейсов из теста выкинуть, а вообще как-то всё в несколько строк превратить), или и то, что я написал столько кейсов для подобных задач, нормально?


/// <summary>
/// Here applies integer division with MidpointRounding.AwayFromZero.
/// </summary>
/// <param name="testBaseStat"></param>
/// <param name="testStat"></param>
/// <param name="expected"></param>
[TestCase(0, 0, 0)]
[TestCase(0, 1, 0)]
[TestCase(0, -1, 0)]
[TestCase(1, 0, 1)]
[TestCase(1, 1, 1)]
[TestCase(1, -1, 1)]
[TestCase(1, 49, 1)]
[TestCase(1, -49, 1)]
[TestCase(1, 50, 2)]
[TestCase(1, -50, 1)]
[TestCase(1, 51, 2)]
[TestCase(1, -51, 0)]
[TestCase(1, 99, 2)]
[TestCase(1, -99, 0)]
[TestCase(1, 100, 2)]
[TestCase(1, -100, 0)]
[TestCase(1, 101, 2)]
[TestCase(1, -101, 0)]
[TestCase(1, 220, 3)]
[TestCase(1, -220, 0)]
[TestCase(2, 1, 2)]
[TestCase(2, 49, 3)]
[TestCase(2, 50, 3)]
[TestCase(2, 51, 3)]
[TestCase(2, 74, 3)]
[TestCase(2, 75, 4)]
[TestCase(2, 99, 4)]
[TestCase(2, 100, 4)]
[TestCase(2, 101, 4)]
[TestCase(2, 149, 5)]
[TestCase(2, 150, 5)]
[TestCase(2, 151, 5)]
[TestCase(11, 221, 35)]
[TestCase(11, 239, 37)]
[TestCase(int.MaxValue, int.MinValue, 0)]
[TestCase(int.MinValue, int.MinValue, 0)]
public void AddModifier_PercentValueModifier_ValueChangesCorrectly(int testBaseStat, int testStat, int expected)
{
    var charStat = new CharacterStat(testBaseStat);
    charStat.AddModifier(new StatModifier(testStat, StatModifierType.Percent));
    var result = charStat.Value;

    Assert.AreEqual(result, expected);
}


Вот собственно имплементация, но это так, для дополнения (тесты все проходят)


void CalculateValue()
{
    var finalValue = BaseValue; // testBaseStat in the test

    foreach (var mod in StatMidifiers)
    {
        var percentage = mod.Value < -100 ? -100 : mod.Value;
        var valueToRound = finalValue * (1 + percentage / 100.0);
        finalValue = (int)Math.Round(valueToRound, MidpointRounding.AwayFromZero);
    }

    Value = finalValue;
}
#1 
  max2_2000 прохожий16.10.21 21:05
NEW 16.10.21 21:05 
в ответ alex445 16.10.21 19:08
TDD, то вроде сначала в тестах описываем бизнес логику, а потом пишем код, чтобы тестам удовлетворяли?

нет, не так.

#2 
alex445 старожил16.10.21 21:40
NEW 16.10.21 21:40 
в ответ max2_2000 16.10.21 21:05, Последний раз изменено 16.10.21 21:41 (alex445)

Ладно, не привязываясь к точным определениям. Я написал требования, сделал тест. Это нормальный тест, или как надо?


Или по-другому. Я сначала написал логику по требованиям. На логику сделал тест. Нормальный тест, или как надо?


Меня больше интересует, нормальный ли тест. Привёл пример логики, которую он тестирует.

#3 
  max2_2000 прохожий17.10.21 14:20
NEW 17.10.21 14:20 
в ответ alex445 16.10.21 21:40

если тдд, то вначале создаем тесты бизнес-логики, и заглушки этой логики, которые не проходят тесты. затем начинаем продвигаться вперед, доводя логику до проходимости тестов. "я так думаю" (с)

#4 
Программист коренной житель18.10.21 09:58
NEW 18.10.21 09:58 
в ответ alex445 16.10.21 19:08


Если TDD, то вроде сначала в тестах описываем бизнес логику, а потом пишем код, чтобы тестам удовлетворяли?

TDD - итеративный процесс.

Грубо говоря, если ты делаешь калькулятор, то пишешь 1-й тест:

[TestCase(0, 0, 0)]
public void AddModifier_PercentValueModifier_ValueChangesCorrectly(int summand1, int summand2, int expected)
{
    var calc= new Calc();
    int result calc.Add(summand1, summand2);
    Assert.AreEqual(expected, result);
}

и код для будет таким:

public class Calc
{
    public int Add(int summand1, int summand2)
    {
        return 0;
    }
}

После этого добавляем новые тесты и делаем рефакторинг после каждого теста.


1) к целочисленным значениям должно применяться целое или равное 0 число процентов - т.е. из целого числа может получиться дробное;

Ну это совсем необязательно ;)


2) при применении отрицательного числа процентов число должно уменьшаться, при этом -100% означает обнуление числа, и дальнейшее снижение процентов должно приводить всё к тому же обнулению;

Странное требование, ну да ладно :)


3) результат должен округляться по математическим правилам до целого - т.е. при ,5 в бОльшую сторону, при -,5

Ну ОК.



В чем разница между этими тестами:

[TestCase(1, -1, 1)]
[TestCase(1, -49, 1)]
[TestCase(1, -50, 1)]

В чем разница между этими тестами:

[TestCase(1, -51, 0)]
[TestCase(1, -99, 0)]
[TestCase(1, -100, 0)]
[TestCase(1, -101, 0)]
[TestCase(1, -220, 0)]

В чем разница между этими тестами:

[TestCase(0, 0, 0)]
[TestCase(0, 1, 0)]
[TestCase(1, 0, 1)]
[TestCase(1, 1, 1)]
[TestCase(1, 49, 1)]
[TestCase(1, 50, 2)]
[TestCase(1, 51, 2)]
[TestCase(1, 99, 2)]
[TestCase(1, 100, 2)]
[TestCase(1, 101, 2)]
[TestCase(1, 220, 3)]
[TestCase(2, 1, 2)]
[TestCase(2, 49, 3)]
[TestCase(2, 50, 3)]
[TestCase(2, 51, 3)]
[TestCase(2, 74, 3)]
[TestCase(2, 75, 4)]
[TestCase(2, 99, 4)]
[TestCase(2, 100, 4)]
[TestCase(2, 101, 4)]
[TestCase(2, 149, 5)]
[TestCase(2, 150, 5)]
[TestCase(2, 151, 5)]
[TestCase(11, 221, 35)]
[TestCase(11, 239, 37)]


Вопрос - можно ли принципиально проще и короче (т.е. не просто несколько кейсов из теста выкинуть, а вообще как-то всё в несколько строк превратить), или и то, что я написал столько кейсов для подобных задач, нормально?

Можно. Делай так, как говорится в учебнике - добавляй по одному тест-кейсу. При этом как только ты добавил тест-кейс, он должен быть красным. После это этого ты этот тест-кейс фиксишь и после этого делаешь рефакторинг. После рефакторинга все тесты должны оставаться зелеными.

#5 
alex445 старожил18.10.21 10:44
NEW 18.10.21 10:44 
в ответ Программист 18.10.21 09:58

TDD - итеративный процесс.

Грубо говоря, если ты делаешь калькулятор, то пишешь 1-й тест:

и код для будет таким:
После этого добавляем новые тесты и делаем рефакторинг после каждого теста.

Но это же невероятно долго! Если писать сначала логику, а потом добавлять тесты, то я могу с первого раза написать то, что надо.


Опять же, насколько я могу понять, TDD работает хорошо только для заранее хорошо проработанных требований и описанной бизнес-логике. Если предполагается много раз менять её ещё на этапе написания программы, то TDD будет просто тормозить разработку? А если разрабатываешь вообще прототип, и ещё не знаешь, что в конце должно получиться, то и требований и описания бизнес-логики конкретной нет, а всё лишь в общих чертах, и TDD вообще трудно применить - непонятно, что конкретно тестировать. Правильно?

#6 
alex445 старожил18.10.21 10:51
NEW 18.10.21 10:51 
в ответ Программист 18.10.21 09:58
1) к целочисленным значениям должно применяться целое или равное 0 число процентов - т.е. из целого числа может получиться дробное;

Ну это совсем необязательно ;)

Это не обязательно, но возможно. Причём очень возможно. К единице примените 40%, получится дробное по логике, но не по коду (в коде округлится согласно правилам округления языка программирования).


Я имею ввиду, что тестируемый код должен обрабатывать такие вещи и иметь логику округления, которая может отличаться от логики округления языка. Например, можно считать, что любое, даже мизерное превышение над целым должно округляться в сторону бОльшего целого (5,00001 = 6) - тогда это надо оговорить в описании задачи и это должно отражаться в тестах. В приведённых мной тестах другое правило - обычное математическое округление.


2) при применении отрицательного числа процентов число должно уменьшаться, при этом -100% означает обнуление числа, и дальнейшее снижение процентов должно приводить всё к тому же обнулению;

Странное требование, ну да ладно :)

Я хотел описать, что такие проценты, как например -200%, должны означать то же, что и -100%. Просто в зависимости от реализации кода, который вычисляет проценты, если не вводить пороговые проверки, то можно получить неожиданные результаты при числе процентов меньше -100.

#7 
alex445 старожил18.10.21 10:58
NEW 18.10.21 10:58 
в ответ Программист 18.10.21 09:58, Последний раз изменено 18.10.21 11:08 (alex445)
В чем разница между этими тестами:

Вот я и пытаюсь выяснить - мало, много или достаточно я тестовых кейсов применил.


[TestCase(1, -1, 1)]
[TestCase(1, -49, 1)]
[TestCase(1, -50, 1)]

Здесь проверка, правильно ли округляются пороговые значения около половины (условие, когда десятичная часть получается равной ",5" или близко к этому). Проверял на единице и брал значения результата чуть ниже порогового, равное и чуть выше.


[TestCase(1, -51, 0)]
[TestCase(1, -99, 0)]
[TestCase(1, -100, 0)]
[TestCase(1, -101, 0)]
[TestCase(1, -220, 0)]

То же самое, но проверка, а правильно ли округляются значения вблизи целого (т.е. когда есть десятичная часть типа ",01").


Последний тест кейс - отрицательное число процентов, которое меньше -100%, и которое должно работать как -100%.


[TestCase(0, 0, 0)]
[TestCase(0, 1, 0)]
[TestCase(1, 0, 1)]
[TestCase(1, 1, 1)]
[TestCase(1, 49, 1)]
[TestCase(1, 50, 2)]
[TestCase(1, 51, 2)]
[TestCase(1, 99, 2)]
[TestCase(1, 100, 2)]
[TestCase(1, 101, 2)]
[TestCase(1, 220, 3)]
[TestCase(2, 1, 2)]
[TestCase(2, 49, 3)]
[TestCase(2, 50, 3)]
[TestCase(2, 51, 3)]
[TestCase(2, 74, 3)]
[TestCase(2, 75, 4)]
[TestCase(2, 99, 4)]
[TestCase(2, 100, 4)]
[TestCase(2, 101, 4)]
[TestCase(2, 149, 5)]
[TestCase(2, 150, 5)]
[TestCase(2, 151, 5)]
[TestCase(11, 221, 35)]
[TestCase(11, 239, 37)]

Проверка, как код работает с нулём.

Как код работает с нулём процентов.

Опять пороговые значения, но в положительной области.

Проверка с чётными и нечётными числами (единица и двойка) - опять целые и пороговые дробные.

Для двойки пороговые проценты будут 50+-1, 75+-1, 100+-1.

Последние два теста - просто наугад взятые числа "побольше".

#8 
Программист коренной житель18.10.21 11:06
NEW 18.10.21 11:06 
в ответ alex445 18.10.21 10:44
Но это же невероятно долго!

В начале да.


Если писать сначала логику, а потом добавлять тесты, то я могу с первого раза написать то, что надо.

Очевидно, что не можешь ;) Если бы мог, то этой темы бы не было.


Опять же, насколько я могу понять, TDD работает хорошо только для заранее хорошо проработанных требований и описанной бизнес-логике. Если предполагается много раз менять её ещё на этапе написания программы, то TDD будет просто тормозить разработку?

Нет. Я бы даже сказал, что в случаях, когда нет хорошо проработанных требований и описаний - TDD просто must have. Т.к. TDD проявит противоречивые требования и хотелки еще на стадии проектирования. И это в результате поможет избежать крупных переделок и/или костылей в будущем.


А если разрабатываешь вообще прототип, и ещё не знаешь, что в конце должно получиться, то и требований и описания бизнес-логики конкретной нет, а всё лишь в общих чертах, и TDD вообще трудно применить - непонятно, что конкретно тестировать. Правильно?

Неправильно. Если ты не знаешь что тестировать, то смысла в тестах конечно нет... впрочем, в коде, который ничего не делает смысла тоже нет :)

#9 
alex445 старожил18.10.21 11:07
NEW 18.10.21 11:07 
в ответ Программист 18.10.21 09:58
Вопрос - можно ли принципиально проще и короче (т.е. не просто несколько кейсов из теста выкинуть, а вообще как-то всё в несколько строк превратить), или и то, что я написал столько кейсов для подобных задач, нормально?

Можно. Делай так, как говорится в учебнике - добавляй по одному тест-кейсу. При этом как только ты добавил тест-кейс, он должен быть красным. После это этого ты этот тест-кейс фиксишь и после этого делаешь рефакторинг. После рефакторинга все тесты должны оставаться зелеными.

Звучит правильно. Но верен ли такой подход для подобных задач, как у меня - математика? Ведь видно же, что тест кейсов просто дофига, и делать два-три десятка итераций - это писать одну простую функцию (процентное округление по кастомным правилам) чуть ли не весь день.


С другой стороны, я думаю, что именно этот случай как раз такой, когда можно сделать исключение и написать сначала код по требованиям бизнес-логики, который уже заранее удовлетворит большинству тест кейсов (если программист не дурак, он сможет это сделать), а потом уже написать тест кейсы и править баги в коде. Я сделал так и у меня получилось примерно 5-7 итераций - т.е. я написал требования, написал код, написал тесты с пороговыми значениями (не все, а что пока в голову пришли), возникли ошибки, поправил код, добавил тест кейсов, снова поправил. Если бы я делал как вы написали, то я бы сделал число итераций по числу тест кейсов... ну или не стал бы валять дурака, а почитал бы требования и понял хотя бы примерно, что требуется, и сразу написал бы код, который удовлетворял бы подавляющему числу тест кейсов.


Моё мнение - иногда проще СНАЧАЛА написать код не по тестам, а по требованиям. Потом догонять тестами и итерациями. Но, как я понимаю, TDD против этого?

#10 
alex445 старожил18.10.21 11:11
NEW 18.10.21 11:11 
в ответ Программист 18.10.21 11:06
Если писать сначала логику, а потом добавлять тесты, то я могу с первого раза написать то, что надо.

Очевидно, что не можешь ;) Если бы мог, то этой темы бы не было.


Немного не так. Как я уже написал, я имею ввиду, что с первого раза можно написать БЛИЗКО к тому, что надо. А если опытный - ОЧЕНЬ БЛИЗКО. Вплоть до очевидности и ПРЯМО ТО, ЧТО НАДО. Поэтому в задачах, где предполагается много тест кейсов, и значительная часть которых явно (по опыту) покрывается первой же итерацией, лучше сначала написать код, а потом тест кейсы к нему. Нет?

#11 
alex445 старожил18.10.21 11:15
NEW 18.10.21 11:15 
в ответ Программист 18.10.21 11:06
Опять же, насколько я могу понять, TDD работает хорошо только для заранее хорошо проработанных требований и описанной бизнес-логике. Если предполагается много раз менять её ещё на этапе написания программы, то TDD будет просто тормозить разработку?

Нет. Я бы даже сказал, что в случаях, когда нет хорошо проработанных требований и описаний - TDD просто must have. Т.к. TDD проявит противоречивые требования и хотелки еще на стадии проектирования. И это в результате поможет избежать крупных переделок и/или костылей в будущем.

Мне это трудно понять. Или я не знаю границы применимости эти высказываний. Я могу работать по такой методике на работе, если требуется, но в своих собственных проектах я предпочитаю сначала написать какой-то базовый код, а потом уже тестировать его и подгонять под требования.

#12 
Программист коренной житель18.10.21 11:43
NEW 18.10.21 11:43 
в ответ alex445 18.10.21 10:51
Это не обязательно, но возможно. Причём очень возможно. К единице примените 40%, получится дробное по логике, но не по коду (в коде округлится согласно правилам округления языка программирования).

Начнем с того, что это нифига не требование :) Формулируй требования к черному ящику. Результат твоих вычислений - целочисленный. Так что когда ты говоришь о числах с плавающей точкой - ты вмешиваешься в работу черного ящика.

В твоем же случаевсе можно реализовать на интах - достаточно просто умножить на 100 ;) В конце вычисления соответственно разделить на 100. При этом для правильного округления надо просто домавить 50 ;) Т.е. (result + 50) / 100. И никаких чисел с плавающей точкой.

Я хотел описать, что такие проценты, как например -200%, должны означать то же, что и -100%.

Но ты же понимаешь, что это странное требование ;)

Ок, пример: 10 - 100% должно стать нулем. Нет проблем. -10 - 10% - должно стать -11, но при этом -10 - 100% почему-то должно стать нулем :) Тебя ничего не смущает в этом требовании? :)

#13 
Программист коренной житель18.10.21 11:57
NEW 18.10.21 11:57 
в ответ alex445 18.10.21 10:58
Здесь проверка, правильно ли округляются пороговые значения около половины (условие, когда десятичная часть получается равной ",5" или близко к этому). Проверял на единице и брал значения результата чуть ниже порогового, равное и чуть выше.

Ты же понимаешь, что если x.5 округляется до x+1, то x.51 и x.99 тоже округляются до x+1 ;)


То же самое, но проверка, а правильно ли округляются значения вблизи целого (т.е. когда есть десятичная часть типа ",01").

Таже история - если x.49 округляется до х, то х.01 тоже округляется до х.


Последний тест кейс - отрицательное число процентов, которое меньше -100%, и которое должно работать как -100%.

-101 тоже меньше 100. Зачем нужен тест с -220?


Проверка, как код работает с нулём.

Зачем? Там какие-то требования к 0?


Как код работает с нулём процентов.

С 0 процентов какая-то особая работа?


Опять пороговые значения, но в положительной области.

Поврорение уже существующих тестов?


Проверка с чётными и нечётными числами (единица и двойка) - опять целые и пороговые дробные.

Где-то есть требования, что с четными и нечетными числами надо по разному работать?


Для двойки пороговые проценты будут 50+-1, 75+-1, 100+-1.

Да пофиг, ты пороги уж проверил :)


Последние два теста - просто наугад взятые числа "побольше".

Что ты этими тестами тестируешь?


Ты понимаешь, что каждый тест должен тестировать уникальное поведение? Если 2 теста тестируют одно и тоже, то один из тестов можно смело выкинуть.

#14 
Программист коренной житель18.10.21 12:01
NEW 18.10.21 12:01 
в ответ alex445 18.10.21 11:07
Но верен ли такой подход для подобных задач, как у меня - математика?

Да :)


Ведь видно же, что тест кейсов просто дофига

На самом деле, тест-кейсов там не дофига :) Больше половины твоих тест-кейсов можно выкинуть, т.к. они не тестируют ничего нового. Попробуй сделать описанную тобой задачу как по учебнику ;)


Но, как я понимаю, TDD против этого?

Да, TDD против :)

#15 
alex445 старожил18.10.21 13:13
NEW 18.10.21 13:13 
в ответ Программист 18.10.21 11:43, Последний раз изменено 18.10.21 13:39 (alex445)
В твоем же случаевсе можно реализовать на интах - достаточно просто умножить на 100 ;) В конце вычисления соответственно разделить на 100. При этом для правильного округления надо просто домавить 50 ;) Т.е. (result + 50) / 100. И никаких чисел с плавающей точкой.

Но это кастомные "хаки" округления, и кроме того я теряю два порядка в длине целых чисел, что может быть существенным. Я хочу максимального отсутствия хаков и максимального использования стандартных библиотек, в том числе для округлений. И чтобы программист не заморачивался, что где-то длина интов режется на 2 порядка.


Я хотел описать, что такие проценты, как например -200%, должны означать то же, что и -100%.
Но ты же понимаешь, что это странное требование ;)

Можно написать код, который будет без этого требования формально проходить тесты, генерируя дичь. Например, у меня получалось, что число просто уходило в отрицательные значения.

Например, 10 - 250% = -15.


Ок, пример: 10 - 100% должно стать нулем. Нет проблем. -10 - 10% - должно стать -11, но при этом -10 - 100% почему-то должно стать нулем :) Тебя ничего не смущает в этом требовании? :)

Пожалуй, нужно ещё ввести запрет обработки отрицательных чисел для такого округления. Или просто юзать беззнаковые целые. Но тогда код может уходить в другой конец - Int32.Max.


Видите, как сложно писать тесты? А до этого писать требования обычными словами? - За всем и не уследишь.

#16 
alex445 старожил18.10.21 13:37
NEW 18.10.21 13:37 
в ответ Программист 18.10.21 11:57, Последний раз изменено 18.10.21 13:40 (alex445)
Ты же понимаешь, что если x.5 округляется до x+1, то x.51 и x.99 тоже округляются до x+1 ;)

Если пользоваться стандартными правилами округления. А если хакерить и кастомизить, то не факт. Короче, проверка от дурака. На всякий случай.


-101 тоже меньше 100. Зачем нужен тест с -220?

Просто любое число меньше -100.


А нужно ли комментировать каждый TestCase? Вы так делаете?


Проверка, как код работает с нулём.
Зачем? Там какие-то требования к 0?

Требование простое: 0 при округлении должен быть всегда 0.


Код, удовлетворящий тестам, может содержать баги - например, неправильно обрабатывать 0. Кто знает, кто там как округляет. При применении стандартных библиотечных функций проблем с 0 быть не должно. Но тестер не знает, что будет применяться.


Вообще, насколько я знаю, что в математике, что по идее в программировании, должны проверяться разные пороговые (граничные), асимптотические и нулевые значения. Обычно там разные функции могут повести себя непредсказуемо или резко менять своё значение.


Опять пороговые значения, но в положительной области.
Поврорение уже существующих тестов?

Да кто их знает, итих программёров, что они там напишут? Их же сейчас всех подряд берут, по объявлениям!


Проверка с чётными и нечётными числами (единица и двойка) - опять целые и пороговые дробные.
Где-то есть требования, что с четными и нечетными числами надо по разному работать?

Работать надо одинаково. Но то же опасение - старнадртыне функции округления не требуют таких подробных проверок. Самописные костыли - возможно требуют.


Насколько я понял, я в тестах должен доверять самописным округлениям и вообще коду не из проверенных многими людьми до меня источников. У самописных фреймворков должны быть свои тесты - я не должен тестировать сторонние фреймворки, даже самописные?


Вобщем, если не быть таким подозрительным и не тестировать за других то, что я не должен тестировать, то можно сократить количество моих тестов раза в 2-3?


Не всегда очевидны очевидные вещи.



#17 
Программист коренной житель18.10.21 14:17
NEW 18.10.21 14:17 
в ответ alex445 18.10.21 13:13
Но это кастомные "хаки" округления

Это не хаки округления :) Просто когда формулируешь требования к "черному ящику" не лезь не в свое дело - не предписывай ящику как ему работать. Ограничивайся требованиями к результатам.


кроме того я теряю два порядка в длине целых чисел

Должен заметить, что никаких ограничений у тебя нет. Если хочешь подумать о пограничных значениях, то попробуй сделать тест, который проверяет увеличение int.MaxValue на 5% :)


Я хочу максимального отсутствия хаков и максимального использования стандартных библиотек, в том числе для округлений.

Свои хотлки ты можешь реализовывать в своем коде. На этапе составления требований речь идет о "черном ящике" и ты не можешь предписывать черному ящику как ему работать.


И чтобы программист не заморачивался, что где-то длина интов режется на 2 порядка.

Составляй грамотно требования, а не придумывай оправдания не лету. Пример с увеличением int.MaxValue на 5% я уже привел. В твои требования этот пример укладывается, вот только получится хрень :)


Можно написать код, который будет без этого требования формально проходить тесты, генерируя дичь. Например, у меня получалось, что число просто уходило в отрицательные значения.Например, 10 - 250% = -15.

А почему это дичь? :)


Видите, как сложно писать тесты?

Ничего сложно :)

А до этого писать требования обычными словами? - За всем и не уследишь.

Именно поэтому требования обычно делаются одними людьми, а тесты пишутся другими :)

#18 
Программист коренной житель18.10.21 14:30
NEW 18.10.21 14:30 
в ответ alex445 18.10.21 13:37
На всякий случай.

Ну так проверял бы тогда все варианты с шагом в 1% для всех чисел :)


Просто любое число меньше -100.

Так зачем нужен тест с -220, когда строчкой выше был для -101?


А нужно ли комментировать каждый TestCase? Вы так делаете?

Я стараюсь в названии теста указывать тестируемую фичу, входные условия и ожидаемый результат. Тесты не комментирую.


Требование простое: 0 при округлении должен быть всегда 0.

А 100 при округлении должно быть чем-то другим? Чем 0 отличается от 100? или от 123456?


Но тестер не знает, что будет применяться.

Тестер не пишет юнит-тесты и не работает по TDD. TDD - инструмент программиста. В задачу юнит-тестирования не входит поиск новых багов.


Вообще, насколько я знаю, что в математике, что по идее в программировании, должны проверяться разные пороговые (граничные), асимптотические и нулевые значения. Обычно там разные функции могут повести себя непредсказуемо или резко менять своё значение.

Да, но пограничные значения всегда разные. В выражении 1/(x+2) проверять надо поведение при х=-2, а 0 никого не интересует.


я не должен тестировать сторонние фреймворки, даже самописные?

Ты вообще не должен тестировать внешний код. Даже если ты используешь свой собственный фреймворк, в месте, где он используется этот фреймворк является внешним кодом.

При написании юнит теста ты должен исходить из того, что внешний код не содержит багов.


#19 
alex445 старожил18.10.21 14:57
NEW 18.10.21 14:57 
в ответ Программист 18.10.21 14:17
Можно написать код, который будет без этого требования формально проходить тесты, генерируя дичь. Например, у меня получалось, что число просто уходило в отрицательные значения.Например, 10 - 250% = -15.

А почему это дичь? :)

Надо 0.

Например, на персонажа могут быть навешаны дебаффы, которые загонят какой-нибудь его показатель в -250%. Тогда показатель должен просто обнулиться, а не уйти в отрицательное значение.


Просто любое число меньше -100.

Так зачем нужен тест с -220, когда строчкой выше был для -101?

Требование простое: 0 при округлении должен быть всегда 0.

А 100 при округлении должно быть чем-то другим? Чем 0 отличается от 100? или от 123456?

Я думаю, это от недостатка опыта написания тестов и вообще опыта. Я хотел порогое значение вблизи 100% (или -100%), и просто большое число процентов, существенно больше порогового, но не равное другому пороговому. Объяснить не могу - мне кажется, что это не помешало бы.

#20 
1 2 3 4 все