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

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

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

Ответ 1

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

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

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

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

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

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

Только Test One Thing

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

Надеюсь, это означает, что мы можем перейти от "геттеров и сеттеров":)

Ответ 2

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

A unit test как:

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

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

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

Ответ 3

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

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

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

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

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

Это то, где удавалось выполнить модульное тестирование.

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

Затем я создал первый 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);
    }

Ответ 4

Если они действительно тривиальны, то не утруждайте себя тестированием. Например, если они реализованы следующим образом:

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

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

Ответ 5

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

Ответ 6

Другой канонический ответ. Это, я считаю, от Рона Джеффриса:

Проверяйте только тот код, который вы хотите использовать.

Ответ 7

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

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

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

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

Два товарища по команде будут обсуждать, кто сбросил мяч, и не смогли выполнить модульные тесты, когда set/получает morphed, чтобы включить логику, которая может выйти из строя, но не покрывается unit test. У товарища по команде, который изначально написал набор/получат, будет легче выходить из этого чистого, если бы тесты были реализованы с первого дня на простом наборе/получении.

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

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

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

Ответ 8

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

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

Ответ 9

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

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

Ответ 10

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

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

Ответ 11

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

Ответ 12

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

Ответ 13

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

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

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

Ответ 14

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

Ответ 15

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

Ответ 16

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

Ответ 17

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

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

Ответ 18

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

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

Ответ 19

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

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

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

Ответ 20

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

Ответ 21

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

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

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

Ответ 22

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

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

Вот что я сделал бы в вашем положении:

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

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

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

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

Ответ 23

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

Ответ 24

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

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

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

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

Ответ 25

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

Ответ 26

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

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

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

Сначала пройдите, напишите unit test для каждого общедоступного метода в вашем "Бизнес-логическом слое".

Если бы у меня был класс вроде этого:

   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()
        {

        }
    }

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

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

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

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

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

Ответ 27

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

Ответ 28

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

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

Ответ 29

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

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

Ответ 30

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

Код с большим количеством тестов, но небольшой охват не был хорошо протестирован. Тем не менее, код со 100% -ным охватом, но не тестирующий ошибки и ошибки, также невелик.

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

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

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

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