단위 테스트를 작성할 때 무엇을 테스트해야 하는지 어떻게 알 수 있나요?[닫은]

StackOverflow https://stackoverflow.com/questions/62625

  •  09-06-2019
  •  | 
  •  

문제

C#을 사용하려면 다음과 같은 클래스가 필요합니다. User 사용자 이름, 비밀번호, 활성 플래그, 이름, 성, 전체 이름 등이 포함됩니다.

방법이 있어야 한다 인증하다 그리고 구하다 사용자.메소드에 대한 테스트만 작성하면 되나요?그리고 속성이 .Net의 getter 및 setter이므로 속성 테스트에 대해 걱정해야 합니까?

도움이 되었습니까?

해결책

이에 대한 많은 훌륭한 답변도 내 질문에 있습니다."TDD 시작 - 과제?솔루션?추천?"

내 문서도 살펴보는 것이 좋습니다. 블로그 게시물 (부분적으로 내 질문에서 영감을 얻었습니다) 이에 대한 좋은 피드백을 받았습니다.즉:

어디서부터 시작해야 할지 모르시나요?

  • 새로 시작하세요.새 코드를 작성할 때만 테스트 작성에 대해서만 생각해보십시오.이것은 이전 코드 또는 완전히 새로운 기능을 재 작업 할 수 있습니다.
  • 간단하게 시작하세요.도망 치지 말고 TDD-esque뿐만 아니라 머리를 테스트 프레임 워크로 만들려고하지 마십시오.Debug.Assert가 제대로 작동합니다.그것을 출발점으로 사용하십시오.프로젝트를 엉망으로 만들거나 종속성을 생성하지 않습니다.
  • 긍정적으로 시작하세요.당신은 당신의 공예를 개선하려고 노력하고 있습니다.나는 정체되어 행복하고 더 나은 것을 시도하지 않는 많은 개발자들을 보았습니다.당신은 옳은 일을하고 있습니다. 이것을 기억하면 포기하는 것을 막는 데 도움이 될 것입니다.
  • 도전을 준비하세요.테스트를 시작하기가 매우 어렵습니다.도전을 기대하지만 기억하십시오 - 도전을 극복 할 수 있습니다.

기대하는 것에 대해서만 테스트하세요

나는 처음 시작했을 때 실제 문제가 있었기 때문에 일어날 수있는 모든 가능한 문제를 알아 내고 테스트하고 수정하려고 노력했기 때문에 끊임없이 앉았습니다.이것은 두통을 일으키는 빠른 방법입니다.테스트는 실제 yagni 프로세스 여야합니다.문제가 있다는 것을 알고 있다면 테스트를 작성하십시오.그렇지 않으면 귀찮게하지 마십시오.

한 가지만 테스트하세요

각 테스트 케이스는 한 가지만 테스트해야합니다.테스트 케이스 이름에“그리고”를 넣는 것을 발견하면 뭔가 잘못하고 있습니다.

이것이 우리가 "getter 및 setter"에서 나아갈 수 있음을 의미하기를 바랍니다. :)

다른 팁

언어가 아닌 코드를 테스트하세요.

다음과 같은 단위 테스트:

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

이는 컴파일러를 작성하는 경우에만 유용하며, instanceof 방법이 작동하지 않습니다.

적용할 언어에 의존할 수 있는 항목을 테스트하지 마세요.귀하의 경우에는 인증 및 저장 방법에 중점을 두고 해당 필드 중 일부 또는 전부에서 null 값을 정상적으로 처리할 수 있는지 확인하는 테스트를 작성하겠습니다.

이로 인해 단위 테스트가 시작되었고 매우 기뻤습니다.

우리는 방금 단위 테스트를 시작했습니다.오랫동안 나는 그것을 시작하는 것이 좋을 것이라는 것을 알고 있었지만 어떻게 시작해야 할지, 그리고 더 중요한 것은 무엇을 테스트해야 할지 전혀 몰랐습니다.

그런 다음 우리는 회계 프로그램의 중요한 코드 부분을 다시 작성해야 했습니다.이 부분은 다양한 시나리오가 포함되어 있어 매우 복잡했습니다.제가 말씀드리고 있는 부분은 이미 회계시스템에 입력된 매출 및/또는 구매 송장을 결제하는 방법입니다.

결제 옵션이 너무 다양해서 코딩을 어떻게 시작해야 할지 몰랐습니다.송장은 $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);
    }

정말 사소한 것이라면 굳이 테스트하지 마세요.예를 들어, 다음과 같이 구현된다면;

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

반면, getter/setter에서 비밀번호를 암호화하고 해독하는 등 영리한 작업을 수행하고 있다면 테스트해 보세요.

규칙은 작성하는 모든 논리를 테스트해야 한다는 것입니다.getter 및 setter에 특정 기능을 구현했다면 테스트할 가치가 있다고 생각합니다.일부 비공개 필드에만 값을 할당하는 경우에는 신경쓰지 마세요.

이 질문은 어떤 방법이 테스트되고 어떤 방법이 테스트되지 않는지에 대해 어디에서 선을 긋는지에 대한 질문인 것 같습니다.

값 할당을 위한 setter 및 getter는 일관성과 향후 성장을 염두에 두고 만들어졌으며, 시간이 지나면 setter/getter가 더 복잡한 작업으로 발전할 수 있을 것으로 예상됩니다.일관성과 향후 성장을 위해서도 이러한 방법에 대한 단위 테스트를 실시하는 것이 합리적입니다.

특히 추가 기능을 추가하기 위해 변경하는 동안 코드 안정성이 주요 목표입니다.나는 테스트 방법론에 setter/getter를 포함했다는 이유로 해고된 사람을 본 적이 없습니다. 그러나 마지막으로 알고 있거나 기억할 수 있는 테스트 방법이 단순한 set/get 래퍼였으면 좋겠다고 생각하는 사람들이 있다고 확신합니다. 경우가 더 길어집니다.

어쩌면 팀의 다른 구성원이 현재 테스트가 필요하지만 테스트를 생성하지 않은 논리를 포함하도록 설정/가져오기 메서드를 확장했을 수도 있습니다.그러나 이제 코드에서 이러한 메서드를 호출하고 있으며 변경된 사실을 인식하지 못하고 심층적인 테스트가 필요합니다. 개발 및 QA에서 수행하는 테스트는 결함을 유발하지 않지만 릴리스 첫날의 실제 비즈니스 데이터는 결함을 유발합니다. 그것을 트리거하십시오.

이제 두 팀원은 실패할 수 있지만 단위 테스트에서 다루지 않는 논리를 포함하도록 세트/모핑된 경우 누가 공을 떨어뜨리고 단위 테스트에 실패했는지에 대해 토론할 것입니다.원래 set/get을 작성한 팀 동료는 간단한 set/get에 대해 테스트가 첫날부터 구현된 경우 이 정리 작업을 더 쉽게 완료할 수 있습니다.

내 의견은 사소한 테스트라도 단위 테스트를 통해 모든 메서드를 다루는 "낭비" 시간이 몇 분이면 앞으로 골치 아픈 일과 돈/비즈니스 평판 손실 및 누군가의 직업 손실을 줄일 수 있다는 것입니다.

그리고 당신이 사소한 메서드를 단위 테스트로 래핑했다는 사실은 그 후배 팀원이 사소한 메서드를 사소하지 않은 메서드로 변경하고 테스트를 업데이트하라는 메시지를 표시할 때 볼 수 있으며 이제 결함이 억제되었기 때문에 아무도 문제에 빠지지 않습니다. 생산에 도달하는 것부터.

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

또 다른 표준 답변.저는 Ron Jeffries가 이렇게 말했습니다.

작업하려는 코드만 테스트하세요.

상용구 코드를 테스트하는 것은 시간 낭비이지만 Slavo가 말했듯이 getter/setter에 부작용을 추가하는 경우 해당 기능을 수반하는 테스트를 작성해야 합니다.

테스트 기반 개발을 수행하는 경우 먼저 계약(예: 인터페이스)을 작성한 다음 예상 결과/동작을 문서화하는 해당 인터페이스를 실행하는 테스트를 작성해야 합니다. 그 다음에 단위 테스트에서 코드를 건드리지 않고 메서드를 직접 작성하세요.마지막으로 코드 적용 도구를 사용하여 테스트가 코드의 모든 논리 경로를 실행하는지 확인하세요.

비공개 필드를 설정하는 것 외에 추가 동작이 없는 getter 및 setter와 같은 정말 사소한 코드는 테스트하기에 과잉입니다.3.0 C#에는 컴파일러가 private 필드를 처리하므로 프로그래밍할 필요가 없는 구문 설탕도 있습니다.

나는 보통 수업에서 기대하는 동작을 확인하는 매우 간단한 테스트를 많이 작성합니다.두 개의 숫자를 더하는 것과 같은 간단한 일이라도 말이죠.나는 간단한 테스트 작성과 몇 줄의 코드 작성 사이를 많이 전환합니다.그 이유는 내가 생각하지 못한 일이 망가질까 두려워하지 않고 코드를 변경할 수 있기 때문입니다.

모든 것을 테스트해야 합니다.지금은 getter와 setter가 있지만 언젠가 유효성 검사나 다른 작업을 수행하기 위해 이를 다소 변경할 수도 있습니다.오늘 작성한 테스트는 내일 모든 것이 평소대로 작동하는지 확인하는 데 사용됩니다.테스트를 작성할 때 "지금은 사소한 일이다"와 같은 고려 사항을 잊어야 합니다.Agile 또는 테스트 기반 컨텍스트에서는 향후 리팩토링을 가정하여 테스트해야 합니다.또한 매우 긴 문자열이나 기타 "나쁜" 콘텐츠와 같은 정말 이상한 값을 입력하려고 했습니까?글쎄요...당신의 코드가 미래에 얼마나 심하게 남용될 수 있는지 결코 추측하지 마십시오.

일반적으로 광범위한 사용자 테스트를 작성하는 것은 한편으로는 지치는 일이라는 것을 알았습니다.다른 한편으로는 항상 애플리케이션이 어떻게 작동해야 하는지에 대한 귀중한 통찰력을 제공하고 다음과 같은 쉬운 (그리고 잘못된) 가정을 버리는 데 도움이 됩니다.사용자 이름의 길이는 항상 1000자 미만입니다.

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

getter 및 setter에 대한 단위 테스트를 작성하는 것은 나쁠 것이 없습니다.지금은 내부적으로 필드 가져오기/설정을 수행할 수도 있지만 앞으로는 유효성 검사 논리나 테스트해야 하는 속성 간 종속성이 있을 수 있습니다.그것에 대해 생각하는 동안 지금 작성하고 그 때가 오면 다시 수정하는 것을 기억하는 것이 더 쉽습니다.

일반적으로 메서드가 특정 값에 대해서만 정의된 경우 해당 값에 대해 테스트합니다. 그리고 이상 허용되는 것의 경계.즉, 메소드가 예상한 대로 작동하는지 확인하세요. 하지만 그 이상은 없어.이것은 중요합니다. 왜냐하면 실패할 때는 일찍 실패하고 싶기 때문입니다.

상속 계층에서는 다음 사항을 테스트해야 합니다. LSP 규정 준수.

나중에 일부 유효성 검사를 수행할 계획이 아니라면 기본 getter 및 setter를 테스트하는 것은 나에게 그다지 유용하지 않은 것 같습니다.

민첩한 개발의 맥락에서 단위 테스트를 이해하기 때문에 Mike, 그렇습니다. getter와 setter를 테스트해야 합니다(공개적으로 표시된다고 가정).단위 테스트의 전체 개념은 소프트웨어 단위(이 경우 클래스)를 테스트하는 것입니다. 블랙 박스.getter 및 setter는 외부에서 볼 수 있으므로 인증 및 저장과 함께 테스트해야 합니다.

Authenticate 및 Save 메서드가 속성을 사용하는 경우 테스트는 속성을 간접적으로 터치합니다.속성이 데이터에 대한 액세스만 제공하는 한 명시적인 테스트는 필요하지 않습니다(100% 적용 범위를 목표로 하지 않는 한).

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

개인적으로 나는 "깨질 수 있는 모든 것을 테스트"하고 간단한 getter(또는 더 나은 자동 속성)는 깨지지 않을 것입니다.나는 간단한 반환문이 실패한 적이 없기 때문에 테스트도 해본 적이 없습니다.게터 내에 계산이 있거나 다른 형태의 명령문이 있는 경우 이에 대한 테스트를 확실히 추가할 것입니다.

개인적으로 나는 사용한다 Moq 모의 개체 프레임워크로 사용한 다음 내 개체가 주변 개체를 필요한 방식으로 호출하는지 확인합니다.

클래스의 모든 메소드 실행을 UT로 처리하고 메소드 반환 값을 확인해야 합니다.여기에는 특히 멤버(속성)가 초기화 중에 큰 메모리 할당이 필요한 복잡한 클래스인 경우 getter 및 setter가 포함됩니다.예를 들어 매우 큰 문자열(또는 그리스 기호가 있는 문자열)을 사용하여 setter를 호출하고 결과가 올바른지 확인합니다(잘리지 않음, 인코딩이 양호함 등).

또한 적용되는 단순 정수의 경우 정수 대신 long을 전달하면 어떻게 되나요?이것이 바로 당신이 UT를 쓰는 이유입니다 :)

실제 속성 설정을 테스트하지는 않습니다.나는 이러한 속성이 소비자에 의해 어떻게 채워지고 무엇으로 채워지는지에 대해 더 관심을 가질 것입니다.모든 테스트에서는 테스트 시간/비용을 고려하여 위험을 평가해야 합니다.

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

속성이 사소하고 누군가가 속성에 버그를 도입할 가능성이 없다면 단위 테스트를 수행하지 않는 것이 안전합니다.

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

이상적으로는 수업을 작성하면서 단위 테스트를 수행했을 것입니다.이것이 테스트 주도 개발을 사용할 때의 의미입니다.각 기능 포인트를 구현할 때 테스트를 추가하고 테스트를 통해 극단적인 경우도 포함하는지 확인합니다.

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

귀하의 입장에서 제가 할 일은 다음과 같습니다.

  1. 핵심 기능을 테스트하는 기본 테스트 세트를 작성합니다.
  2. Ncover를 다운로드하여 테스트에 실행해 보세요.이 시점에서 테스트 적용 범위는 아마도 약 50%일 것입니다.
  3. 약 80%-90% 범위에 도달할 때까지 극단적인 경우를 다루는 테스트를 계속 추가하세요.

이는 회귀에 대한 좋은 버퍼 역할을 하는 훌륭한 작업 단위 테스트 세트를 제공합니다.

이 접근 방식의 유일한 문제점은 코드가 다음과 같아야 한다는 것입니다. 디자인된 이런 방식으로 테스트할 수 있습니다.초기에 커플링 실수를 했다면 쉽게 높은 커버리지를 얻을 수 없을 것입니다.

이것이 바로 코드를 작성하기 전에 테스트를 작성하는 것이 정말 중요한 이유입니다.느슨하게 결합된 코드를 작성해야 합니다.

명백히 작동하는(상용구) 코드를 테스트하지 마세요.따라서 setter와 getter가 단지 "propertyvalue = value" 및 "return propertyvalue"인 경우 테스트하는 것은 의미가 없습니다.

get/set도 구현 방법에 따라 이상한 결과를 초래할 수 있으므로 메서드로 취급해야 합니다.

이들에 대한 각 테스트에서는 호출이 예상된 방식으로 반환/실패하는지 확인하기 위해 허용 가능한 속성과 허용되지 않는 속성을 모두 정의하여 속성에 대한 매개 변수 집합을 지정해야 합니다.

또한 SQL 주입의 예와 같은 보안 문제점을 인식하고 이를 테스트해야 합니다.

그렇습니다. 속성 테스트에 대해 걱정할 필요가 있습니다.

저는 getter와 setter가 간단한 작업만 할 때 이를 테스트하는 것은 어리석은 일이라고 생각합니다.개인적으로 나는 사용 패턴을 다루기 위해 복잡한 단위 테스트를 작성하지 않습니다.나는 정상적인 실행 동작과 내가 생각할 수 있는 많은 오류 사례를 처리했는지 확인하기 위해 충분한 테스트를 작성하려고 노력합니다.버그 보고서에 대한 응답으로 더 많은 단위 테스트를 작성하겠습니다.나는 코드가 요구 사항을 충족하는지 확인하고 향후 수정을 더 쉽게 만들기 위해 단위 테스트를 사용합니다.뭔가를 깨뜨리면 테스트가 실패할 것이라는 사실을 알면 코드를 바꾸고 싶은 마음이 훨씬 더 커집니다.

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

        }
    }

어떤 작업을 수행하기 위해 작성한 코드를 검증하는 테스트를 작성하세요.여러 항목을 반복하고 각각에 대해 무언가를 변경하는 경우 동일한 작업을 수행하는 테스트를 작성하고 실제로 발생한 것을 확인하세요.

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

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

쉽게 테스트를 작성할 수 있도록 비즈니스 로직을 사용자 인터페이스 계층 외부에 유지하면 좋은 결과를 얻을 수 있습니다.

나는 추천한다 TestDriven.Net 또는 ReSharper 둘 다 Visual Studio에 쉽게 통합됩니다.

글쎄, 그것이 깨질 수 있다고 생각한다면, 그것에 대한 테스트를 작성하세요.나는 일반적으로 setter/getter를 테스트하지 않지만 이름과 성을 연결하는 User.Name에 대해 하나를 만든다고 가정하면 테스트를 작성하여 누군가 성과 이름의 순서를 변경하면 적어도 그 사람은 알 것입니다. 그는 테스트된 것을 변경했습니다.

표준 대답은 "파괴 할 수있는 모든 것을 테스트"입니다. 속성이 파손되지 않을 것이라고 확신한다면 테스트하지 마십시오.

그리고 일단 뭔가 고장난 것이 발견되면(버그를 발견하면) 분명히 그것을 테스트해야 한다는 뜻입니다.버그를 재현하는 테스트를 작성하고, 실패하는 것을 관찰한 다음, 버그를 수정하고, 테스트 통과를 지켜보세요.

Authenticate 및 Save 메소드에 대한 여러 테스트를 작성하는 것이 좋습니다.성공 사례(모든 매개변수가 제공되고, 모든 항목의 철자가 정확함 등) 외에도 다양한 실패 사례(잘못되거나 누락된 매개변수, 해당되는 경우 사용할 수 없는 데이터베이스 연결 등)에 대한 테스트를 갖는 것이 좋습니다.나는 추천한다 NUnit을 사용한 C#의 실용적인 단위 테스트 참고로.

다른 사람들이 언급했듯이 getter 및 setter에 조건부 논리가 없으면 getter 및 setter에 대한 단위 테스트는 과잉입니다.

코드에서 테스트가 필요한 위치를 정확하게 추측하는 것이 가능하지만 일반적으로 이 추측을 뒷받침하는 측정항목이 필요하다고 생각합니다.내 관점에서 단위 테스트는 코드 적용 범위 측정항목과 밀접하게 연관되어 있습니다.

테스트는 많지만 적용 범위는 작은 코드는 제대로 테스트되지 않았습니다.즉, 100% 커버리지를 가지지만 경계 및 오류 사례를 테스트하지 않는 코드도 좋지 않습니다.

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

"쓰레기 넣기"를 테스트하는 것을 잊지 마세요!

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

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

우리 코드가 더 좋아지네요...기간!

우리 소프트웨어 개발자들이 테스트 주도 개발을 할 때 잊어버리는 것 중 하나는 우리 행동 뒤에 숨은 목적입니다.프로덕션 코드가 이미 준비된 후에 단위 테스트를 작성하는 경우 테스트의 가치는 상당히 낮아집니다(그러나 완전히 손실되지는 않습니다).

단위 테스트의 진정한 정신에 따라 이러한 테스트는 다음과 같습니다. ~ 아니다 주로 우리 코드를 더 많이 "테스트"하기 위해 존재합니다.또는 90%-100% 더 나은 코드 적용 범위를 얻으려면.이것들은 모두 부가 혜택 테스트를 먼저 작성하는 것입니다.큰 보상은 TDD의 자연스러운 프로세스로 인해 우리의 생산 코드가 훨씬 더 잘 작성된다는 것입니다.

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

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

글을 쓰는 행위가 우리에게 느껴진다면 더 많은 단위 테스트 이것이 우리가 더 높은 품질의 제품을 얻는 데 도움이 된다면, 우리는 화물 컬트 테스트 주도 개발의.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top