Тестирование труднодоступного кода

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

if (condition) { code to be tested }

I или со значением true :

if (true || condition) { code to be tested }

Есть ли более элегантный подход?

7
Вы пытаетесь запустить код через отладчик? Я бы посоветовал изучить unit testing . Издевательское решение может помочь сделать ваш код поддающимся проверке. Написав это как единичный тест, вы не только получите возможность проверить свой код сейчас, но и получите тест!
добавлено автор oɔɯǝɹ, источник

5 ответы

Более элегантное решение использует mocks. Принимать решения на основе зависимостей или параметров:

var mock = new Mock();
mock.Setup(foo => foo.IsBar).Returns(true);
var sut = new Sut(mock.Object);
sut.DoSomething();

И в вашей системе:

public void DoSomething()
{
    if (_foo.IsBar)
       //code path to test
}
13
добавлено
@Nogard Я поднял ваш последний комментарий, но у меня проблема с решает проблему с OP проблемой . Хотя этот ответ является солидным советом (после внесения поправок), это больше, чем то, что было задано.
добавлено автор Clodoaldo Neto, источник
Я не понимаю смысл первой строки кода ( if (condition) ... ). Это сарказм?
добавлено автор Clodoaldo Neto, источник
@Nogard Я упомянул использование mocks. И добавил образец кода. Прочитайте ответ до конца, прежде чем комментировать.
добавлено автор Sergey Berezovskiy, источник
@Clodoaldo Я удалю это - просто не используйте постоянные значения, если условия if (true) и т. Д. В этом случае вы можете удалить условие, потому что это не влияет на путь выполнения кода
добавлено автор Sergey Berezovskiy, источник
прочитайте вопрос перед публикацией - хочет реализовать определенный путь кода, который в противном случае был бы достигнут только при условии трудного воспроизведения Цель OP заключается в проверке кода внутри , если , т.е. идти со 100% шансом
добавлено автор Nogard, источник
Конечно, я это видел, но ваш предварительно отредактированный ответ (который я прокомментировал) заявил, что только трудно воспроизвести условие - насмешка также может его использовать. Затем был добавлен образец Mock и он решает проблему OP.
добавлено автор Nogard, источник

Я думаю, что более elegant way использует оператор логического отрицания (!) как;

if (!condition) { code to be tested }

But more safe way for debugging or testing purposes you can use a preprocessor directive (as per my commet). When you finish testing simply remove or change #define UnreachableTest

#define UnreachableTest //should be on the top of the class/page

#if (UnreachableTest) 
    condition = !condition; //or
    condition = true;
#endif

if (condition) { code to be tested }
13
добавлено
@Kaf +1 за хороший ответ :)
добавлено автор bonCodigo, источник
Да, это выглядит более элегантно. С единственным уловом, что он не будет работать, когда условие будет выполнено. Но мне это нравится, и я думаю, это было бы хорошо в большинстве случаев использования.
добавлено автор Clodoaldo Neto, источник
В этом случае вы можете использовать директиву препроцессора , чтобы изменить условие для цели тестирования во время отладки. В виде; #define UnreachableTest наверху ... #if (UnreachableTest) condition =! condition #endif Затем ваш фактический код будет следовать.
добавлено автор Kaf, источник
@AlanBarber: Вы читали OP? он ищет лучший элегантный способ и уже принят в качестве ответа. Также вы должны прочитать мой первый комментарий, как сделать его более практичным.
добавлено автор Kaf, источник
@deworde: Теперь ясно?
добавлено автор Kaf, источник
@deworde: Ну, если это правда, он будет работать независимо от условия (что больше похоже на удаление условия). Если это условие, он будет работать для трудного сделать вид ...
добавлено автор Kaf, источник
@AlanBarber: Я упомянул об этом в своих комментариях. Теперь я отредактировал ответ.
добавлено автор Kaf, источник
@deworde: Как я сказал Алену, я упомянул, как сделать его более практичным/безопасным в моих комментариях. Я добавил свои комментарии к ответу сейчас.
добавлено автор Kaf, источник
@Kaf да, я указываю на опасность бросить "!" в условие. Препроцессорная директива - намного более элегантное и безопасное решение, и я дал вам +1 на этот комментарий.
добавлено автор Alan Barber, источник
Извините, я должен дать -1 на этот ответ. Это очень плохой запах кода, чтобы изменить логическое условие для тестирования. Это опасно, так как это может привести к тому, что кто-то забыл удалить это «!». и в конечном итоге с производственным кодом, имеющим условие перевернутого и создающим ошибки/ошибки.
добавлено автор Alan Barber, источник
Справедливо. Еще один вопрос: любая причина не просто сделать условие = true вместо условия =! Условие?
добавлено автор deworde, источник
Я согласен с Аланом. Этот выглядит как реальный код , а это значит, что когда вы делаете развертку перед выпуском на производство, вы вряд ли заметите это. В этот момент вы очищаете разбитый беспорядок только поврежденных данных, достигших вашей системы в течение 12 часов, прежде чем кто-либо заметил. Сделайте это 500 раз, через 30 разных файлов и результаты «Мир боли». По крайней мере, если (true || ...) можно искать.
добавлено автор deworde, источник
@Kaf Намного лучше, спасибо!
добавлено автор deworde, источник

Ваш подход, с «истинным или», и подход if (! Condition) являются простейшими. Вот такой подход, который мне нравится для больших программ

Создайте функцию, назовем ее testme (const string). И вместо того, чтобы вставлять true в if test, вы вставляете testme с некоторой строкой, которая идентифицирует этот фрагмент кода.

    if ( testme("Location 123") || condition ) { code to be tested }

Затем, используя какой-то конфигурационный файл или аргументы в вашей программе (я предпочитаю config), вы можете полностью контролировать, когда testme («Location 123») вернет true. И вы можете использовать одну и ту же функцию во многих местах. Просто измените конфигурационный файл для проверки каждого из них.

3
добавлено
+1. Я использую логическую переменную, определенную где-то еще для этой цели.
добавлено автор Clodoaldo Neto, источник

Я предполагаю, что это не сценарий единичного теста, поскольку он не упоминался в вопросе. Безусловно, самый простой способ сделать «на лету» тестирование такого кода - это использовать команду Set Next Statement отладчика.

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

2
добавлено
Хорошо +1. Я обязательно его использую. Но в этом конкретном случае, когда я хочу запустить этот путь хотя бы несколько раз, это неудобно.
добавлено автор Clodoaldo Neto, источник

Поместите код, который будет протестирован отдельным методом. Затем вы можете вызвать метод и обойти условное. Теперь вам не придется беспокоиться о добавлении «истины» или, что более важно, забыть удалить его.

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

2
добавлено
Microsoft Stack Jobs
Microsoft Stack Jobs
1 788 участник(ов)

Work & freelance only Microsoft Stack. Feed https://t.me/Microsoftstackjobsfeed Чат про F#: @Fsharp_chat Чат про C#: @CSharpChat Чат про Xamarin: @xamarin_russia Чат общения:@dotnettalks

Microsoft Developer Community Chat
Microsoft Developer Community Chat
584 участник(ов)

Чат для разработчиков и системных администраторов Microsoft Developer Community. __________ Новостной канал: @msdevru __________ Баним за: оскорбления, мат, рекламу, флуд, флейм, спам, NSFW контент, а также большое количество оффтоп тем. @banofbot