it-swarm-ko.tech

단위 테스트를 작성할 때 테스트 할 내용을 어떻게 알 수 있습니까?

C #을 사용하려면 사용자 이름, 비밀번호, 활성 플래그, 이름, 성, 이름 등이있는 User라는 클래스가 필요합니다.

사용자를 인증저장하는 방법이 있어야합니다. 방금 메소드에 대한 테스트를 작성합니까? 그리고 속성이 .Net의 getter 및 setter이므로 속성 테스트에 대해 걱정해야합니까?

127
Mike Roosa

이것에 대한 많은 훌륭한 답변도 내 질문에 있습니다 : " TDD 시작-도전? 솔루션? 권장 사항? "

블로그 게시물 (내 질문에 부분적으로 영감을 얻음)을 살펴 보는 것이 좋습니다. 좋은 의견이 있습니다. 즉:

어디에서 시작할지 모르겠습니까?

  • 새로 시작하십시오. 새 코드를 작성할 때 테스트 작성에 대해서만 생각하십시오. 이전 코드를 다시 작업하거나 완전히 새로운 기능 일 수 있습니다.
  • 간단하게 시작하십시오. TDD와 마찬가지로 테스트 프레임 워크에서 벗어나려고하지 마십시오. Debug.Assert가 제대로 작동합니다. 시작점으로 사용하십시오. 프로젝트를 엉망으로 만들거나 의존성을 만들지 않습니다.
  • 긍정적으로 시작하십시오. 당신은 당신의 기술을 향상시키기 위해 노력하고 있습니다. 나는 정체에 기뻐하고 스스로를 개선하기 위해 새로운 것을 시도하지 않는 많은 개발자를 보았습니다. 당신은 옳은 일을하고 있으며, 이것을 기억하면 포기하는 것을 막을 수 있습니다.
  • 도전을위한 준비를 시작하십시오. 테스트를 시작하기가 매우 어렵습니다. 도전을 기대하되, 도전은 극복 할 수 있습니다.

당신이 기대하는 것만 테스트

처음 시작할 때 발생할 수있는 모든 가능한 문제를 파악한 다음 테스트하고 수정하려고했기 때문에 실제로 문제가 발생했습니다. 이것은 두통에 대한 빠른 방법입니다. 테스트는 실제 YAGNI 프로세스 여야합니다. 문제가 있음을 알고 있으면 테스트를 작성하십시오. 그렇지 않으면 귀찮게하지 마십시오.

하나만 테스트

각 테스트 사례는 한 가지만 테스트해야합니다. 테스트 사례 이름에 "및"을 넣은 것을 발견하면 뭔가 잘못한 것입니다.

나는 이것이 "getters and setters"에서 나아갈 수 있다는 것을 의미한다. :)

130
Rob Cooper

언어가 아닌 코드를 테스트하십시오.

다음과 같은 단위 테스트 :

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

컴파일러를 작성 중이고 instanceof 메소드가 작동하지 않을 가능성이 0이 아닌 경우에만 유용합니다.

언어를 사용하여 시행 할 수있는 것은 테스트하지 마십시오. 귀하의 경우, 귀하의 인증 및 저장 방법에 중점을 둘 것입니다-그리고 그 필드 중 일부 또는 전부에서 null 값을 정상적으로 처리 할 수 ​​있는지 테스트를 작성했습니다.

63
Tim Howland

이것으로 유닛 테스트를 받았고 매우 행복해졌습니다

방금 단위 테스트를 시작했습니다. 오랫동안 나는 그것을 시작하는 것이 좋을 것이라는 것을 알았지 만 시작하는 방법과 더 중요한 것이 무엇인지 테스트하지 못했습니다.

그런 다음 회계 프로그램에서 중요한 코드를 다시 작성해야했습니다. 이 부분은 다양한 시나리오를 포함하기 때문에 매우 복잡했습니다. 내가 말하는 부분은 이미 회계 시스템에 입력 된 판매 및/또는 구매 송장을 지불하는 방법입니다.

지불 옵션이 너무 많기 때문에 코딩을 시작하는 방법을 몰랐습니다. 인보이스는 100 달러 일 수 있지만 고객은 99 달러 만 송금했습니다. 고객에게 판매 송장을 보냈지 만 해당 고객으로부터 구매 송장을 받았을 수도 있습니다. 그래서 당신은 그를 300 달러에 팔았지만 100 달러에 샀습니다. 고객은 잔액을 정산하기 위해 $ 200를 지불 할 것으로 예상 할 수 있습니다. 500 달러에 판매했지만 고객이 250 달러 만 지불하면 어떻게됩니까?

그래서 한 시나리오가 완벽하게 작동하지만 다른 유형의 송장/지불 조합에서는 잘못 될 가능성이 많은 여러 가지 문제를 해결하기 위해 매우 복잡한 문제가있었습니다.

이곳에서 유닛 테스트가 시작되었습니다

판매 및 구매에 대한 송장 목록을 작성하는 방법을 테스트 코드 안에 작성하기 시작했습니다. 그런 다음 실제 지불을 만드는 두 번째 방법을 작성했습니다. 일반적으로 사용자는 사용자 인터페이스를 통해 해당 정보를 입력합니다.

그런 다음 첫 번째 TestMethod를 작성하여 지불 할인없이 단일 송장의 매우 간단한 지불을 테스트했습니다. 시스템의 모든 조치는 은행 지불이 데이터베이스에 저장 될 때 발생합니다. 보시다시피 송장을 만들고, 지불 (은행 거래)을 만들고 거래를 디스크에 저장했습니다. 내 주장에 은행 거래와 연결된 송장에 올바른 숫자가 무엇인지 입력했습니다. 거래 후 지불 횟수, 지불 금액, 할인 금액 및 송장 잔액을 확인합니다.

테스트가 실행 된 후 데이터베이스로 이동하여 예상 한 것이 있는지 다시 확인했습니다.

After 테스트를 작성했는데 결제 방법 (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; }
}

반면에 getter/setter에서 암호를 암호화 및 해독하는 등 영리한 작업을 수행하는 경우 테스트를 수행하십시오.

13
Steve Cooper

규칙은 작성하는 모든 논리를 테스트해야한다는 것입니다. 게터와 세터에서 특정 기능을 구현했다면 테스트 할 가치가 있다고 생각합니다. 그들이 일부 개인 필드에만 값을 할당하는 경우 귀찮게하지 마십시오.

10
Slavo

이 질문은 어떤 메소드가 테스트되고 어떤 메소드를 테스트하지 않는지에 대한 질문입니다.

가치 할당을위한 세터와 게터는 일관성과 미래의 성장을 염두에두고 만들어졌으며, 시간이 지날수록 세터/게터가 더 복잡한 작업으로 발전 할 수 있다고 예측했습니다. 일관성과 미래 성장을 위해 이러한 방법에 대한 단위 테스트를 실시하는 것이 합리적입니다.

추가 기능을 추가하기 위해 변경하는 동안 코드 안정성이 주요 목표입니다. 테스트 방법론에 세터/게터를 포함하여 해고당한 사람은 아무도 모르지만, 마지막으로 알고 있거나 기억할 수있는 방법을 테스트 해보고 싶었던 사람들이 있다고 확신합니다. 더 긴 경우.

어쩌면 팀의 다른 구성원이 set/get 메소드를 확장하여 테스트가 필요하지만 테스트를 작성하지 않은 로직을 포함 할 수있었습니다. 그러나 이제 코드에서 이러한 메소드를 호출하고 있으며 메소드가 변경되어 심층적 인 테스트가 필요하다는 것을 알지 못하며 개발 및 QA에서 수행하는 테스트는 결함을 유발하지 않지만 릴리스 첫 날의 실제 비즈니스 데이터는 트리거하십시오.

두 팀원은 이제 공을 떨어 뜨 렸고 실패했을 수 있지만 유닛 테스트로 다루지 않는 로직을 포함하도록 세트/겟이 모핑 될 때 누가 유닛 테스트에 참여하지 않았는지 토론 할 것입니다. 처음 세트/get을 작성한 팀원은 테스트가 간단한 set/gets에서 첫날부터 구현 된 경우이 정리에서 더 쉬운 시간을 갖습니다.

제 생각에는 단위 테스트, 심지어 사소한 방법으로 모든 방법을 다루는 몇 분의 "폐기"시간이 길을 잃는 두통과 비용 손실/사업 손실 및 다른 사람의 직업 손실을 줄일 수 있다고 생각합니다.

하급 팀원이 사소한 방법을 사소하지 않은 방법으로 변경하고 테스트를 업데이트하라는 메시지를 표시하면 사소한 방법으로 단위 테스트를 래핑했다는 사실을 알 수 있습니다. 생산에 도달하지 못했습니다.

우리가 코딩하는 방식과 코드에서 볼 수있는 규율은 다른 사람들을 도울 수 있습니다.

6
Thomas Carlisle

또 다른 정식 답변. 이것은 론 제프리스의 생각입니다.

작업하려는 코드 만 테스트하십시오.

4
user9397

개인 필드를 설정하는 것보다 추가 동작이없는 게터 및 세터와 같은 사소한 코드는 테스트하기가 너무 어렵습니다. 3.0에서 C #에는 컴파일러가 개인 필드를 관리하는 구문 설탕이 있으므로 프로그래밍 할 필요가 없습니다.

나는 보통 수업에서 기대하는 행동을 확인하는 매우 간단한 테스트를 많이 작성합니다. 두 개의 숫자를 추가하는 것과 같은 간단한 경우에도 마찬가지입니다. 간단한 테스트 작성과 몇 줄의 코드 작성간에 많은 전환이 이루어졌습니다. 그 이유는 내가 생각하지 않은 것을 깨뜨릴 것을 두려워하지 않고 코드를 바꿀 수 있기 때문입니다.

3
Mendelt

모든 것을 테스트해야합니다. 지금 당신은 게터와 세터를 가지고 있지만 언젠가는 그것들을 약간 변경하거나 유효성 검사 또는 다른 것을 할 수 있습니다. 오늘 작성하는 테스트는 내일 사용되어 모든 것이 평상시처럼 작동하는지 확인합니다. 테스트를 작성할 때 "지금은 사소한 것"과 같은 고려 사항을 잊어야합니다. 민첩하거나 테스트 중심의 컨텍스트에서 향후 리팩토링을 가정하고 테스트해야합니다. 또한 매우 긴 문자열 또는 다른 "나쁜"내용과 같은 이상한 값을 입력하려고 했습니까? 글쎄, 나중에는 코드가 얼마나 악용 될 수 있다고 가정해서는 안됩니다.

일반적으로 광범위한 사용자 테스트를 작성하는 것이 힘들다는 것을 알았습니다. 반면에 항상 응용 프로그램이 어떻게 작동 해야하는지에 대한 귀중한 통찰력을 제공하고 쉬운 가정을 버리는 데 도움이됩니다 (예 : 사용자 이름의 길이는 항상 1000 자 미만입니다).

3
Sklivvz

툴킷 또는 오픈 소스 유형의 프로젝트로 끝나는 간단한 모듈의 경우 사소한 게터와 세터를 포함하여 가능한 한 많이 테스트해야합니다. 명심해야 할 것은 특정 모듈을 작성할 때 단위 테스트를 생성하는 것이 매우 간단하고 간단하다는 것입니다. 게터와 세터를 추가하는 것은 최소한의 코드이며 많은 생각없이 처리 할 수 ​​있습니다. 그러나 코드가 더 큰 시스템에 배치되면 이러한 추가 노력으로 기본 클래스의 유형 변경과 같은 기본 시스템의 변경으로부터 보호 할 수 있습니다. 모든 것을 테스트하는 것이 완전한 회귀를 갖는 가장 좋은 방법입니다.

3
Dirigible

상용구 코드를 테스트하는 것은 시간 낭비이지만 Slavo가 말했듯이 게터/세터에 부작용을 추가하면 해당 기능과 함께 테스트를 작성해야합니다.

테스트 중심 개발을 수행하는 경우 먼저 계약 (예 : 인터페이스)을 작성하고 테스트를 작성하여 예상되는 결과/동작을 문서화하는 해당 인터페이스를 실습해야합니다. Then 단위 테스트에서 코드를 건드리지 않고 메서드를 직접 작성하십시오. 마지막으로 코드 커버리지 도구를 잡고 테스트에서 코드의 모든 논리 경로를 테스트해야합니다.

3
warren_s

일반적으로 특정 값에 대해서만 방법이 정의 된 경우 허용 가능한 값의 경계 ( 및 이상 에서 값을 테스트합니다. 다시 말해, 메소드가해야 할 일을 수행하는지 확인하십시오. 그러나 더 이상 아무것도하지 않습니다 . 실패 할 때는 일찍 실패하기 때문에 이것은 중요합니다.

상속 계층에서 LSP 준수를 테스트해야합니다.

기본 게터와 세터 테스트는 나중에 약간의 유효성 검사를 계획하지 않는 한 나에게별로 유용하지 않은 것 같습니다.

2
Rik

잘 깨질 수 있다고 생각되면 테스트를 작성하십시오. 나는 보통 setter/getter를 테스트하지 않지만 User.Name에 대해 하나를 만들라고 말합니다. 이름과 성을 연결하는 테스트를 작성합니다. 누군가 성과 이름의 순서를 변경하면 적어도 그가 알 것입니다. 그는 시험 된 것을 바꿨다.

2
pmlarocque

정식 답변은 "깨질 수있는 모든 것을 테스트"입니다. 속성이 깨지지 않을 것이라고 확신한다면 테스트하지 마십시오.

그리고 무언가가 깨지면 (버그를 발견하면) 분명히 테스트해야 함을 의미합니다. 버그를 재현하기위한 테스트를 작성하고, 실패를 관찰 한 다음 버그를 수정 한 다음 테스트 패스를보십시오.

2
Eric Normand

게터와 세터에 대한 단위 테스트를 작성하는 것이 아프지 않습니다. 현재는 현장에서 필드 가져 오기/설정을 수행하고있을 수도 있지만 향후에는 테스트해야하는 유효성 검사 논리 또는 속성 간 종속성이있을 수 있습니다. 당신이 그것에 대해 생각하고 그때 그때 다시 개조하는 것을 기억하는 동안 지금 그것을 작성하는 것이 더 쉽습니다.

2
Bob King

이상적으로는 수업을 쓸 때 단위 테스트를 수행했을 것입니다. 테스트 중심 개발을 사용할 때 이렇게해야합니다. 각 기능 포인트를 구현할 때 테스트를 추가하여 테스트를 통해 에지 케이스를 커버하는지 확인하십시오.

나중에 테스트를 작성하는 것이 훨씬 고통 스럽지만 실행 가능합니다.

내가 당신의 입장에서하려는 일은 다음과 같습니다.

  1. 핵심 기능을 테스트하는 기본 테스트 세트를 작성하십시오.
  2. NCover를 다운로드하여 테스트에서 실행하십시오. 이 시점에서 테스트 범위는 약 50 % 일 것입니다.
  3. 약 80 % -90 %의 커버리지를 얻을 때까지 Edge 케이스를 커버하는 테스트를 계속 추가하십시오.

이것은 회귀에 대한 좋은 버퍼 역할을 할 수있는 멋진 단위 테스트 세트를 제공해야합니다.

이 방식의 유일한 문제점은이 방식으로 테스트 할 수 있도록 코드가 designed이어야한다는 것입니다. 조기에 커플 링 실수를 한 경우 높은 커버리지를 쉽게 얻을 수 없습니다.

따라서 코드를 작성하기 전에 테스트를 작성해야합니다. 느슨하게 결합 된 코드를 작성하도록합니다.

1
Simon Johnson

코드를 더 좋게 만듭니다 ... 기간!

테스트 주도 개발을 수행 할 때 소프트웨어 개발자가 잊어 버린 한 가지는 행동의 목적입니다. 생산 코드가 이미 적용된 후 단위 테스트를 작성하는 경우 테스트 값이 줄어 듭니다 (그러나 완전히 손실되지는 않습니다).

단위 테스트의 진정한 의미에서 이러한 테스트는 not 기본적으로 더 많은 코드를 "테스트"하기위한 것입니다. 또는 코드 적용 범위가 90 % -100 % 향상됩니다. 이것들은 모두 먼저 테스트를 작성하는 것의 fringe benefit입니다. 가장 큰 장점은 TDD의 자연스러운 프로세스로 인해 프로덕션 코드 끝을 훨씬 잘 작성한다는 것입니다.

이 아이디어를 더 잘 전달할 수 있도록 다음 내용이 도움이 될 수 있습니다.

결함이있는 단위 테스트 이론
목적 소프트웨어 개발

우리가 더 많은 단위 테스트를 쓰는 행위가 우리가 더 높은 품질의 제품을 얻는 데 도움이된다고 생각한다면, 테스트 주도 개발의 Cargo Cult .

1
Scott Saad

분명히 작동하는 (보일러 플레이트) 코드를 테스트하지 마십시오. 따라서 세터와 게터가 "propertyvalue = value"이고 "return propertyvalue"인 경우 테스트하는 것은 의미가 없습니다.

1
erlando

Get/set조차도 구현 방법에 따라 이상한 결과를 초래할 수 있으므로 메소드로 처리해야합니다.

이러한 각 테스트는 속성에 대한 매개 변수 집합을 지정해야하며 허용되는 속성과 허용 할 수없는 속성을 모두 정의하여 호출이 예상 된 방식으로 반환/실패하도록합니다.

또한 SQL 인젝션의 예로 보안 문제를 알고이를 테스트해야합니다.

따라서 속성 테스트에 대해 걱정할 필요가 있습니다.

1
CestLaGalere

게터와 세터가 간단한 조작 만 할 때 테스트하는 것은 어리석은 일이라고 생각합니다. 개인적으로 사용 패턴을 다루기 위해 복잡한 단위 테스트를 작성하지 않습니다. 정상적인 실행 동작과 내가 생각할 수있는 많은 오류 사례를 처리했는지 확인하기 위해 충분한 테스트를 작성하려고합니다. 버그 보고서에 대한 응답으로 더 많은 단위 테스트를 작성하겠습니다. 단위 테스트를 사용하여 코드가 요구 사항을 충족하는지 확인하고 향후 수정을 더 쉽게 만듭니다. 무언가를 깨 뜨리면 테스트가 실패한다는 것을 알면 코드를 더 많이 기꺼이 바꿉니다.

1
Andrei Savu

코드에서 테스트가 필요한 위치를 정확하게 추측 할 수 있지만 일반적으로이 추측을 백업하기위한 메트릭이 필요하다고 생각합니다. 내 관점에서의 단위 테스트는 코드 커버리지 메트릭과 함께 진행됩니다.

많은 테스트가 있지만 작은 적용 범위를 가진 코드는 잘 테스트되지 않았습니다. 즉, 범위가 100 %이지만 경계 및 오류 사례를 테스트하지 않는 코드도 좋지 않습니다.

높은 적용 범위 (최소 90 %)와 가변 입력 데이터 간의 균형을 원합니다.

"쓰레기 투입"을 테스트해야합니다!

또한 단위 테스트는 실패를 확인하지 않으면 단위 테스트가 아닙니다. 주장이 없거나 알려진 예외로 표시된 단위 테스트는 코드가 실행될 때 죽지 않는지를 테스트합니다!

항상 실패 또는 예기치 않은/원치 않는 데이터를보고하도록 테스트를 설계해야합니다!

1
Ray Hayes

GUI 인터페이스 외부에서 테스트 할 수있는 코드를 작성하는 것에 대한 테스트를 작성합니다.

일반적으로 내가 작성하는 모든 논리에는 다른 계층 또는 비즈니스 논리 계층 내에 배치하는 비즈니스 논리가 있습니다.

그런 다음 무언가를하는 테스트를 작성하는 것은 쉬운 일입니다.

먼저 "Business Logic Layer"에서 각 공용 메소드에 대한 단위 테스트를 작성하십시오.

이런 수업이 있다면 :

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

        }
    }

테스트를 작성하여 작성한 코드의 유효성을 검사하십시오. 일련의 사물을 반복하고 각각에 대해 무언가를 변경하는 경우 동일한 일을 수행하는 테스트를 작성하고 실제로 발생한 어설 션을 작성하십시오.

BDD (Behavoir Driven Development)와 같은 다른 많은 접근 방식이 있습니다.이 방법은 더 복잡하고 단위 테스트 기술로 시작하기에 적합하지 않습니다.

따라서 이야기의 교훈은 걱정할 수있는 모든 것을 테스트하고, 작은 크기의 특정 항목을 테스트하는 단위 테스트를 유지하는 것입니다. 많은 테스트가 좋습니다.

테스트를 쉽게 작성할 수 있도록 비즈니스 로직을 사용자 인터페이스 계층 외부에 유지하십시오.

Visual Studio에 쉽게 통합되므로 TestDriven.Net 또는 ReSharper 를 권장합니다.

1
Dean Poulin

민첩한 개발이라는 맥락에서 단위 테스트를 이해하는 것처럼 Mike, 예. 게터와 세터를 공개적으로 볼 수 있다고 가정해야합니다. 단위 테스트의 전체 개념은이 경우 클래스 인 소프트웨어 단위를 블랙 박스 로 테스트하는 것입니다. 게터와 세터는 외부에서 볼 수 있으므로 인증 및 저장과 함께 테스트해야합니다.

1
Onorio Catenacci

인증 및 저장 방법이 속성을 사용하는 경우 테스트에서 속성을 간접적으로 만집니다. 속성이 데이터에 대한 액세스 만 제공하는 한 100 % 적용 범위를 제외하고는 명시적인 테스트가 필요하지 않습니다.

1
Tom Walker

나는 당신의 게터와 세터를 테스트합니다. 누가 코드를 작성하는지에 따라 getter/setter 메소드의 의미를 변경하는 사람들이 있습니다. getter 메소드의 일부로 변수 초기화 및 기타 유효성 검사를 보았습니다. 이런 종류의 것을 테스트하려면 해당 코드를 명시 적으로 다루는 단위 테스트가 필요합니다.

1
Peter Bernier

개인적으로 나는 "깨질 수있는 것을 테스트"하고 간단한 게터 (또는 더 나은 자동 속성)도 깨지지 않습니다. 나는 간단한 반환 진술에 실패하지 않았으므로 테스트를 해본 적이 없습니다. 게터가 그 안에 또는 다른 형태의 진술로 계산한다면, 나는 분명히 그에 대한 테스트를 추가 할 것입니다.

개인적으로 Moq 를 모의 객체 프레임 워크로 사용하고 내 객체가 주변 객체를 정상적으로 호출하는지 확인합니다.

1
tronda

UT로 클래스의 모든 메소드 실행을 처리하고 메소드 리턴 값을 확인해야합니다. 여기에는 특히 멤버 (속성)가 복잡한 클래스 인 경우 게터 및 세터가 포함됩니다. 초기화 도중 큰 메모리 할당 : 예를 들어 매우 큰 문자열 (또는 그리스 기호가있는 문자열)로 setter를 호출하고 결과가 올바른지 (잘라 내지 않거나 인코딩이 좋은지) 확인하십시오.

간단한 정수도 적용되는 경우-정수 대신 long을 전달하면 어떻게됩니까? 그것이 당신이 UT for :)라고 쓰는 이유입니다.

1
m_pGladiator

클래스 테스트는 다음을 확인해야합니다.

  1. 메서드 및 속성은 예상 값을 반환
  2. 유효하지 않은 인수가 제공 될 때 적절한 예외가 발생합니다.
  3. 주어진 메소드가 호출 될 때 클래스와 다른 오브젝트 간의 상호 작용이 예상대로 발생합니다.

물론 게터와 세터에 특별한 논리가 없다면 Authenticate 및 Save 메소드의 테스트에서이를 다루어야하지만 그렇지 않으면 설명 테스트를 작성해야합니다.

1
Crippledsmurf

Authenticate 및 Save 메소드에 대해 여러 테스트를 작성하는 것이 좋습니다. 성공 사례 (모든 매개 변수가 제공되고 모든 철자가 올바른 경우 등) 외에도 다양한 실패 사례 (잘못된 매개 변수 또는 누락 된 매개 변수, 적용 가능한 경우 사용할 수없는 데이터베이스 연결 등)에 대한 테스트를 수행하는 것이 좋습니다. NUnit을 사용한 C #의 단위 테스트 를 참조하십시오.

다른 사람들이 말했듯이 게터와 세터에 조건부 논리가 없다면 게터와 세터에 대한 단위 테스트는 과도합니다.

1
Scott Lawrence

실제 속성 설정을 테스트하지는 않습니다. 소비자가 해당 속성을 채우는 방법과 속성을 채우는 데 더 관심이 있습니다. 모든 테스트에서는 테스트 시간/비용으로 위험을 평가해야합니다.

1
Bloodhound

가능한 한 단위 테스트를 사용하여 "모든 사소한 코드 블록"을 테스트해야합니다.

당신의 속성이 사소하고 누군가 버그를 일으킬 가능성이 없다면, 단위 테스트를하지 않는 것이 안전해야합니다.

Authenticate () 및 Save () 메소드는 테스트하기에 좋은 후보처럼 보입니다.

1
user7015

가치가없는 코드를 작성하는 것은 항상 나쁜 생각입니다. 제안 된 테스트는 프로젝트에 가치를 추가하지 않기 때문에 (또는 매우 근접한) 것입니다. 그런 다음 실제로 가치를 제공하는 코드 작성에 소비 할 수있는 귀중한 시간을 낭비하고 있습니다.

0
pjesi

두 번째 깨질 수있는 것을 테스트바보 같은 테스트를 작성하지 마십시오. 그러나 가장 중요한 신조는 당신이 찾은 것을 테스트합니다 : 어떤 메소드가 이상하게 동작하는 데이터 세트를 설명하는 테스트를 이상하게 작성한다면, 버그를 수정하고 막대가 녹색으로 변하는 것을보십시오. 또한 "경계"데이터 값 (null, 0, MAX_INT, 빈 목록 등)을 테스트하십시오.

0
Manrico Corazzi

단위 테스트 또는 실제 테스트를 작성할 때 테스트 대상의 경계 조건을보고 테스트 대상을 결정합니다. 예를 들어, is_prime이라는 함수가 있습니다. 다행스럽게도 이름에서 알 수 있듯이 정수 객체가 소수인지 여부를 알려줍니다. 이를 위해 객체를 사용한다고 가정합니다. 이제 알려진 범위의 프라임 및 비 프라임 객체에 대해 유효한 결과가 발생했는지 확인해야합니다. 그것이 시작점입니다.

기본적으로 함수, 메소드, 프로그램 또는 스크립트에서 발생하는 일을 확인한 다음 동일한 코드에서 발생하는 일 not 을 확인하십시오. 이것이 테스트의 기초입니다. should 코드에 무슨 일이 일어나고 있는지에 대해 더 잘 알고 있으면 테스트를 수정할 준비를하십시오.

0
Dan

내가 본 가장 좋은 방법은 한 눈에 알 수없는 모든 것을 테스트하는 것입니다. 더 많은 것은 언어/환경 테스트를 시작합니다.

0
user74754