it-swarm-ru.tech

Как вы знаете, что тестировать при написании модульных тестов?

При использовании C # мне нужен класс с именем User, который имеет имя пользователя, пароль, активный флаг, имя, фамилию, полное имя и т.д.

Должны быть методы для аутентификации и сохранения пользователя. Я просто пишу тест для методов? И мне даже нужно беспокоиться о тестировании свойств, поскольку они являются геттерами и сеттерами .Net?

126
Mike Roosa

Многие отличные ответы на это также на мой вопрос: " Начало TDD - Проблемы? Решения? Рекомендации? "

Могу ли я также порекомендовать взглянуть на мою запись в блоге (которая была частично вдохновлена ​​моим вопросом), я получил несколько хороших отзывов об этом. А именно:

Я не знаю с чего начать?

  • Начните заново. Думайте о написании тестов только тогда, когда пишете новый код. Это может быть переработка старого кода или совершенно новая функция.
  • Начните просто. Не убегайте и не пытайтесь осмыслить среду тестирования, а также быть в стиле TDD. Debug.Assert работает отлично. Используйте это как отправную точку. Это не портит ваш проект и не создает зависимости.
  • Начните позитивно. Вы пытаетесь улучшить свое ремесло, чувствуете себя хорошо по этому поводу. Я видел множество разработчиков, которые рады стагнации и не пробуют новые вещи, чтобы улучшить себя. Вы делаете правильные вещи, помните об этом, и это поможет вам не сдаваться.
  • Начните готов к испытанию. Начать тестирование довольно сложно. Ожидайте вызов, но помните - проблемы могут быть преодолены.

Только тест на то, что вы ожидаете

У меня были настоящие проблемы, когда я только начинал, потому что я постоянно сидел там, пытаясь выяснить каждую возможную проблему, а затем пытался ее проверить и исправить. Это быстрый способ головной боли. Тестирование должно быть настоящим процессом YAGNI. Если вы знаете, что есть проблема, тогда напишите тест для нее. В противном случае, не беспокойтесь.

Только проверить одну вещь

Каждый тестовый случай должен проверять только одну вещь. Если вы когда-нибудь обнаружите, что ставите "и" в имени тестового примера, вы делаете что-то не так.

Я надеюсь, что это означает, что мы можем двигаться дальше от "добытчиков и сеттеров" :)

130
Rob Cooper

Проверьте свой код, а не язык.

Модульный тест вроде:

Integer i = new Integer(7);
assert (i.instanceOf(integer));

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

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

62
Tim Howland

Это привело меня к юнит-тестированию и сделало меня очень счастливым

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

Затем нам пришлось переписать важный кусок кода в нашей бухгалтерской программе. Эта часть была очень сложной, так как включала много разных сценариев. Часть, о которой я говорю, - это метод оплаты счетов-фактур продаж и/или покупок, уже введенных в систему учета.

Я просто не знал, как начать его кодировать, поскольку было так много разных способов оплаты. Счет может быть 100 долларов, но клиент перечислил только 99 долларов. Возможно, вы отправили счета-фактуры покупателю, но вы также приобрели его у этого покупателя. Итак, вы продали его за 300 долларов, но купили за 100 долларов. Вы можете ожидать, что ваш клиент заплатит вам 200 долларов США для урегулирования баланса. А что, если вы продали за 500 долларов, но покупатель платит вам только 250 долларов?

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

Здесь на помощь пришли юнит-тесты.

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

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

После запуска теста я бы пошел в базу данных и дважды проверил, было ли то, что я ожидал.

После Я написал тест, начал кодировать метод оплаты (часть класса BankHeader). В коде мне надоел только код, чтобы сделать первый тестовый проход. Я еще не думал о других, более сложных сценариях.

Я запустил первый тест, исправил небольшую ошибку, пока мой тест не пройдет.

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

При проверке на корректность со скидкой на оплату я также проверял простую оплату. Оба теста должны пройти, конечно.

Затем я прошел путь к более сложным сценариям.

1) Придумайте новый сценарий

2) Написать тест по этому сценарию

3) Запустите этот единственный тест, чтобы увидеть, пройдет ли он

4) Если бы не было, я бы отладил и изменил код, пока он не пройдет.

5) Во время изменения кода я продолжал запускать все тесты

Вот как мне удалось создать очень сложный способ оплаты. Без модульного тестирования я не знал, как начать кодирование, проблема казалась ошеломляющей. С тестированием я мог бы начать с простого метода и постепенно расширять его, гарантируя, что более простые сценарии будут работать.

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

Если я позже подумаю о новом сценарии, я могу просто добавить его в тесты, чтобы увидеть, работает он или нет. Если нет, я могу изменить код, но все равно быть уверенным, что другие сценарии по-прежнему работают правильно. Это сэкономит дни и дни на этапе обслуживания и исправления ошибок.

Да, даже в протестированном коде все еще могут быть ошибки, если пользователь делает то, о чем вы не думали или мешает ему

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

public class TestPayments
{
    InvoiceDiaryHeader invoiceHeader = null;
    InvoiceDiaryDetail invoiceDetail = null;
    BankCashDiaryHeader bankHeader = null;
    BankCashDiaryDetail bankDetail = null;



    public InvoiceDiaryHeader CreateSales(string amountIncVat, bool sales, int invoiceNumber, string date)
    {
        ......
        ......
    }

    public BankCashDiaryHeader CreateMultiplePayments(IList<InvoiceDiaryHeader> invoices, int headerNumber, decimal amount, decimal discount)
    {
       ......
       ......
       ......
    }


    [TestMethod]
    public void TestSingleSalesPaymentNoDiscount()
    {
        IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>();
        list.Add(CreateSales("119", true, 1, "01-09-2008"));
        bankHeader = CreateMultiplePayments(list, 1, 119.00M, 0);
        bankHeader.Save();

        Assert.AreEqual(1, bankHeader.BankCashDetails.Count);
        Assert.AreEqual(1, bankHeader.BankCashDetails[0].Payments.Count);
        Assert.AreEqual(119M, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount);
        Assert.AreEqual(0M, bankHeader.BankCashDetails[0].Payments[0].PaymentDiscount);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance);
    }

    [TestMethod]
    public void TestSingleSalesPaymentDiscount()
    {
        IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>();
        list.Add(CreateSales("119", true, 2, "01-09-2008"));
        bankHeader = CreateMultiplePayments(list, 2, 118.00M, 1M);
        bankHeader.Save();

        Assert.AreEqual(1, bankHeader.BankCashDetails.Count);
        Assert.AreEqual(1, bankHeader.BankCashDetails[0].Payments.Count);
        Assert.AreEqual(118M, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount);
        Assert.AreEqual(1M, bankHeader.BankCashDetails[0].Payments[0].PaymentDiscount);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance);
    }

    [TestMethod]
    [ExpectedException(typeof(ApplicationException))]
    public void TestDuplicateInvoiceNumber()
    {
        IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>();
        list.Add(CreateSales("100", true, 2, "01-09-2008"));
        list.Add(CreateSales("200", true, 2, "01-09-2008"));

        bankHeader = CreateMultiplePayments(list, 3, 300, 0);
        bankHeader.Save();
        Assert.Fail("expected an ApplicationException");
    }

    [TestMethod]
    public void TestMultipleSalesPaymentWithPaymentDiscount()
    {
        IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>();
        list.Add(CreateSales("119", true, 11, "01-09-2008"));
        list.Add(CreateSales("400", true, 12, "02-09-2008"));
        list.Add(CreateSales("600", true, 13, "03-09-2008"));
        list.Add(CreateSales("25,40", true, 14, "04-09-2008"));

        bankHeader = CreateMultiplePayments(list, 5, 1144.00M, 0.40M);
        bankHeader.Save();

        Assert.AreEqual(1, bankHeader.BankCashDetails.Count);
        Assert.AreEqual(4, bankHeader.BankCashDetails[0].Payments.Count);
        Assert.AreEqual(118.60M, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount);
        Assert.AreEqual(400, bankHeader.BankCashDetails[0].Payments[1].PaymentAmount);
        Assert.AreEqual(600, bankHeader.BankCashDetails[0].Payments[2].PaymentAmount);
        Assert.AreEqual(25.40M, bankHeader.BankCashDetails[0].Payments[3].PaymentAmount);

        Assert.AreEqual(0.40M, bankHeader.BankCashDetails[0].Payments[0].PaymentDiscount);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[1].PaymentDiscount);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[2].PaymentDiscount);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[3].PaymentDiscount);

        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[1].InvoiceHeader.Balance);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[2].InvoiceHeader.Balance);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[3].InvoiceHeader.Balance);
    }

    [TestMethod]
    public void TestSettlement()
    {
        IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>();
        list.Add(CreateSales("300", true, 43, "01-09-2008")); //Sales
        list.Add(CreateSales("100", false, 6453, "02-09-2008")); //Purchase

        bankHeader = CreateMultiplePayments(list, 22, 200, 0);
        bankHeader.Save();

        Assert.AreEqual(1, bankHeader.BankCashDetails.Count);
        Assert.AreEqual(2, bankHeader.BankCashDetails[0].Payments.Count);
        Assert.AreEqual(300, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount);
        Assert.AreEqual(-100, bankHeader.BankCashDetails[0].Payments[1].PaymentAmount);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[1].InvoiceHeader.Balance);
    }
38
eroijen

Если они действительно тривиальны, тогда не беспокойтесь о тестировании. Например, если они реализованы так;

public class User
{
    public string Username { get; set; }
    public string Password { get; set; }
}

Если, с другой стороны, вы делаете что-то умное (например, шифрование и дешифрование пароля в получателе/​​установщике), тогда проведите тест.

13
Steve Cooper

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

10
Slavo

Этот вопрос, кажется, является вопросом о том, где можно провести черту между тем, какие методы тестируются, а какие нет.

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

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

Возможно, другой член команды расширил методы set/get, включив в них логику, которая теперь нуждается в проверке, но не создала тесты. Но теперь ваш код вызывает эти методы, и вы не знаете, что они изменились и нуждаются в углубленном тестировании, и тестирование, которое вы проводите в разработке и QA, не вызывает дефект, но реальные бизнес-данные в первый день выпуска делают вызвать его.

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

Мое мнение таково, что несколько минут "потерянного" времени на ВСЕ методы с модульными тестами, даже тривиальными, могут сэкономить дни головной боли в будущем, потери денег/репутации бизнеса и потери чьей-либо работы.

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

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

5
Thomas Carlisle

Еще один канонический ответ. Это, я полагаю, от Рона Джеффриса:

Только протестируйте код, который вы хотите работать.

4
user9397

Действительно тривиальный код, такой как методы получения и установки, которые не имеют никакого дополнительного поведения, чем установка частного поля, излишни для тестирования. В 3.0 C # даже имеет некоторый синтаксический сахар, где компилятор заботится о приватном поле, поэтому вам не нужно его программировать.

Я обычно пишу много очень простых тестов, проверяющих поведение, которое я ожидаю от своих классов. Даже если это простые вещи, такие как добавление двух чисел. Я много переключаюсь между написанием простого теста и написанием нескольких строк кода. Причина этого в том, что я могу изменить код, не боясь, что нарушу то, о чем не думал.

3
Mendelt

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

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

3
Sklivvz

Для простых модулей, которые могут оказаться в наборе инструментов или в проекте с открытым исходным кодом, вы должны как можно больше тестировать, включая тривиальные методы получения и установки. Вы должны иметь в виду, что генерация модульного теста при написании определенного модуля довольно проста и понятна. Добавление геттеров и сеттеров является минимальным кодом и может быть обработано без особых размышлений. Однако после размещения вашего кода в более крупной системе эти дополнительные усилия могут защитить вас от изменений в базовой системе, таких как изменения типов в базовом классе. Тестирование всего - лучший способ завершить регрессию.

3
Dirigible

Тестирование стандартного кода - пустая трата времени, но, как говорит Славо, если вы добавите побочный эффект к своим получателям/установщикам, то вам следует написать тест, сопровождающий эту функциональность.

Если вы занимаетесь разработкой, управляемой тестами, вы должны сначала написать контракт (например, интерфейс), а затем написать тест (ы) для реализации того интерфейса, который документирует ожидаемые результаты/поведение. Тогда сами пишите свои методы, не касаясь кода в ваших модульных тестах. Наконец, возьмите инструмент покрытия кода и убедитесь, что ваши тесты используют все логические пути в вашем коде.

3
warren_s

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

В иерархиях наследования обязательно проверьте соответствие LSP .

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

2
Rik

Не мешает писать модульные тесты для ваших геттеров и сеттеров. Прямо сейчас, они могут просто выполнять поля get/sets, но в будущем у вас может быть логика проверки или зависимости между свойствами, которые необходимо проверить. Проще написать это сейчас, пока вы думаете об этом, а потом вспоминаете, как его модернизировать, если это когда-нибудь наступит.

2
Bob King

В идеале вы бы выполнили свои модульные тесты, когда писали урок. Вот как вы должны это делать при использовании Test Driven Development. Вы добавляете тесты по мере реализации каждой функциональной точки, следя за тем, чтобы вы также покрывали граничные случаи с помощью теста.

Написание тестов впоследствии гораздо более болезненно, но выполнимо.

Вот что я бы сделал в вашей позиции:

  1. Напишите базовый набор тестов, которые проверяют основную функцию.
  2. Получите NCover и запустите его на своих тестах. Ваш тестовый охват, вероятно, будет около 50% на данный момент.
  3. Продолжайте добавлять тесты, которые охватывают ваши пограничные случаи, пока вы не получите покрытие около 80% -90%

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

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

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

1
Simon Johnson

Это делает наш код лучше ... точка!

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

В истинном духе модульного тестирования, эти тесты не являются в первую очередь для того, чтобы "тестировать" больше нашего кода; или получить на 90% -100% лучшее покрытие кода. Это все дополнительные преимущества от написания тестов первыми. Большая выгода состоит в том, что наш производственный код заканчивается, чтобы быть написанным намного лучше из-за естественного процесса TDD.

Чтобы лучше донести эту идею, при чтении может быть полезно следующее:

некорректная теория юнит-тестов
Целенаправленная разработка программного обеспечения

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

1
Scott Saad

Не проверяйте явно работающий (стандартный) код. Так что если ваши сеттеры и геттеры просто "propertyvalue = value" и "return propertyvalue", нет смысла проверять это.

1
erlando

Даже get/set может иметь странные последствия в зависимости от того, как они были реализованы, поэтому их следует рассматривать как методы.

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

Вы также должны знать о проблемах безопасности, как пример SQL-инъекции, и тестировать их.

Так что да, вам нужно беспокоиться о тестировании свойств.

1
CestLaGalere

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

1
Andrei Savu

хорошо, если вы думаете, что он может сломаться, напишите тест для него. Я обычно не тестирую setter/getter, но позвольте сказать, что вы делаете один для User.Name, который объединяет имя и фамилию, я бы написал тест, чтобы, если кто-то изменил порядок для фамилии и имени, по крайней мере, он знал бы он изменил что-то, что было проверено.

1
pmlarocque

Канонический ответ - "проверь все, что может сломаться". Если вы уверены, что свойства не сломаются, не проверяйте их.

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

1
Eric Normand

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

Код с большим количеством тестов, но с небольшим покрытием не был хорошо протестирован. Тем не менее, код со 100% охватом, но без проверки границ и ошибок также не очень хорош.

Вы хотите баланс между высоким охватом (минимум 90%) и переменными входными данными.

Не забудьте проверить на "мусор в"!

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

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

1
Ray Hayes

Я написал бы тест для всего, для чего вы пишете код, который можно тестировать вне интерфейса GUI.

Как правило, любая написанная мной логика, имеющая какую-либо бизнес-логику, помещается внутри другого уровня или уровня бизнес-логики.

Затем написать тесты для всего, что делает что-то, легко.

Первый этап: напишите модульный тест для каждого открытого метода в вашем "Уровне бизнес-логики".

Если бы у меня был такой класс:

   public class AccountService
    {
        public void DebitAccount(int accountNumber, double amount)
        {

        }

        public void CreditAccount(int accountNumber, double amount)
        {

        }

        public void CloseAccount(int accountNumber)
        {

        }
    }

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

   [TestFixture]
    public class AccountServiceTests
    {
        [Test]
        public void DebitAccountTest()
        {

        }

        [Test]
        public void CreditAccountTest()
        {

        }

        [Test]
        public void CloseAccountTest()
        {

        }
    }

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

Есть много других подходов, которые вы можете использовать, а именно Behavoir Driven Development (BDD), которые более сложны и не являются отличным местом для начала с вашими навыками модульного тестирования.

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

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

Я рекомендую TestDriven.Net или ReSharper , поскольку оба легко интегрируются в Visual Studio.

1
Dean Poulin

Как я понимаю, юнит-тесты в контексте гибкой разработки, Майк, да, вам нужно тестировать геттеры и сеттеры (при условии, что они общедоступны). Вся концепция модульного тестирования заключается в тестировании программного модуля, который в данном случае является классом, в виде черный ящик . Поскольку геттеры и сеттеры видимы извне, вам необходимо протестировать их вместе с Authenticate и Save.

1
Onorio Catenacci

Если методы Authenticate и Save используют свойства, то ваши тесты будут косвенно касаться свойств. Поскольку свойства просто предоставляют доступ к данным, явное тестирование не требуется (если только вы не собираетесь на 100% охват).

1
Tom Walker

Я бы проверил ваши геттеры и сеттеры. В зависимости от того, кто пишет код, некоторые люди меняют значение методов получения/установки. Я видел инициализацию переменных и другую проверку как часть методов получения. Чтобы протестировать подобные вещи, вы бы хотели, чтобы модульные тесты явно покрывали этот код.

1
Peter Bernier

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

Лично я использую Moq в качестве фальшивой инфраструктуры объектов, а затем проверяю, что мой объект вызывает окружающие объекты так, как должен.

1
tronda

Вы должны покрыть выполнение каждого метода класса с помощью UT и ​​проверить возвращаемое значение метода. Это включает в себя геттеры и сеттеры, особенно в том случае, если члены (свойства) являются сложными классами, что требует большого выделения памяти во время их инициализации. Например, вызовите установщик с какой-то очень большой строкой (или что-то с греческими символами) и убедитесь, что результат правильный (не усеченный, кодировка хорошая).

В случае простых целых чисел это также применимо - что произойдет, если вы передадите long вместо целого числа? Вот почему вы пишете UT :)

1
m_pGladiator

Тестирование класса должно проверить, что:

  1. методы и свойства возвращают ожидаемые значения
  2. Соответствующие исключения генерируются, когда указан неверный аргумент
  3. Взаимодействия между классом и другими объектами происходят, как и ожидалось, когда вызывается данный метод

Конечно, если геттеры и сеттеры не имеют специальной логики, тогда тесты методов Authenticate иSave должны их охватывать, но в противном случае должен быть написан явный тест

1
Crippledsmurf

Я бы рекомендовал написать несколько тестов для ваших методов аутентификации и сохранения. В дополнение к случаю успеха (когда все параметры указаны, все правильно написано и т.д.), Полезно иметь тесты на различные случаи сбоев (неверные или отсутствующие параметры, недоступные подключения к базе данных, если применимо, и т.д.). Я рекомендую Прагматическое модульное тестирование в C # с NUnit в качестве ссылки.

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

1
Scott Lawrence

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

1
Bloodhound

Вы должны тестировать "каждый нетривиальный блок кода", используя насколько это возможно модульные тесты.

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

Ваши методы Authenticate () и Save () выглядят хорошими кандидатами для тестирования.

1
user7015

Написание кода, который не имеет значения, всегда плохая идея. Поскольку предлагаемый тест не добавляет ценности вашему проекту (или очень близко к нему). Тогда вы тратите драгоценное время на то, чтобы потратить время на написание кода, который действительно приносит пользу.

0
pjesi

Я второй проверяю все, что может сломаться и не пишите глупые тесты. Но самым важным принципом является проверить все, что вы обнаружите, не работает: если какой-то метод ведет себя странно, напишите тест, чтобы набросать набор данных, который делает его неудачным, затем исправьте ошибку и наблюдайте, как полоса становится зеленой. Также проверьте "граничные" значения данных (ноль, 0, MAX_INT, пустые списки, что угодно).

0
Manrico Corazzi

При написании юнит-тестов или вообще любого теста вы определяете, что тестировать, глядя на граничные условия того, что вы тестируете. Например, у вас есть функция is_prime. К счастью, он делает то, что подразумевает его имя, и сообщает вам, является ли целочисленный объект простым или нет. Для этого я предполагаю, что вы используете объекты. Теперь нам нужно проверить, что действительные результаты получены для известного диапазона простых и не простых объектов. Это ваша отправная точка.

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

0
Dan

Лучшее эмпирическое правило, которое я видел, это проверить все, что вы не можете сказать с первого взгляда, наверняка, будет работать правильно. Что-нибудь еще, и вы закончите тестирование языка/среды.

0
user74754