수색…


비고

단위 테스트 는 코드의 개별 단위를 자신이 속한 시스템과 분리하여 테스트하는 프로세스를 설명합니다. 단위를 구성하는 요소는 개별 방법에서 밀접하게 관련된 클래스 그룹 또는 모듈에 이르기까지 시스템마다 다를 수 있습니다.

유닛은 필요시 테스트 더블을 사용하여 종속성과 분리되고 알려진 상태로 설정됩니다. 자극 (메소드 호출, 이벤트, 시뮬레이트 된 데이터)에 대한 반응의 행동은 예상되는 동작에 대해 테스트됩니다.

전체 시스템의 단위 테스트는 사용자 지정 서면 테스트 장치를 사용하여 수행 할 수 있지만, 많은 테스트 프레임 워크가 프로세스를 능률화하고 배관 및 반복적 인 일상 작업을 처리하는 데 도움이되도록 작성되었습니다. 이를 통해 개발자는 테스트하려는 것에 집중할 수 있습니다.

프로젝트에 단위 테스트가 충분할 경우 새로운 기능을 추가하거나 코드 리팩토링을 수정하면 결국 모든 것이 이전과 같이 작동한다는 것을 확인함으로써 쉽게 수행 할 수 있습니다.

일반적으로 백분율로 표시되는 코드 커버리지 는 시스템의 코드 중 단위 테스트에서 다루는 코드의 양을 나타내는 데 사용되는 표준 메트릭입니다. 이것이 얼마나 높아야하는지에 대한 단호하고 빠른 규칙은 없지만 일반적으로 높을수록 좋다는 것을 인정합니다.

테스트 주도 개발 ( Test Driven Development , TDD) 은 개발자가 실패한 단위 테스트를 작성한 후 테스트를 통과하는 프로덕션 코드를 작성하여 코딩을 시작하도록 지정하는 원칙입니다. TDD를 연습 할 때 테스트 자체가 생성되는 코드의 첫 번째 소비자라고 할 수 있습니다. 따라서 코드의 디자인을 감사하고 운전하여 사용하기가 쉽고 가능한 한 강력합니다.

버전

단위 테스트는 버전 번호가없는 개념입니다.

기본 단위 테스트

가장 단순한 단위 테스트는 세 단계로 구성됩니다.

  • 테스트를위한 환경 준비
  • 테스트 할 코드를 실행하십시오.
  • 관찰 된 동작과 일치하는 예상 동작 확인

이 세 단계는 'Arrange-Act-Assert'또는 'Given-When-Then'이라고도합니다.

아래는 C #에서 NUnit 프레임 워크를 사용하는 예제입니다.

[TestFixture]
public CalculatorTest
{
   [Test]
   public void Add_PassSevenAndThree_ExpectTen()
   {
       // Arrange - setup environment
       var systemUnderTest = new Calculator();         

       // Act - Call system under test
       var calculatedSum = systemUnderTest.Add(7, 3);  
       
       // Assert - Validate expected result
       Assert.AreEqual(10, calculatedSum);             
  }
}

필요한 경우 네 번째 정리 단계가 정리됩니다.

종속성이있는 단위 테스트

좋은 단위 테스트는 독립적이지만 코드에는 종종 종속성이 있습니다. 우리는 다양한 종류의 테스트 더블 을 사용하여 테스트를위한 의존성을 제거합니다. 가장 간단한 테스트 복식 중 하나는 스텁입니다. 실제 종속성 대신에 하드 코드 된 반환 값이있는 함수입니다.

// Test that oneDayFromNow returns a value 24*60*60 seconds later than current time

let systemUnderTest = new FortuneTeller()       // Arrange - setup environment
systemUnderTest.setNow(() => {return 10000})    //   inject a stub which will 
                                                //   return 10000 as the result

let actual = systemUnderTest.oneDayFromNow()    // Act - Call system under test

assert.equals(actual, 10000 + 24 * 60 * 60)     // Assert - Validate expected result

프로덕션 코드에서 oneDayFromNow 는 Date.now ()를 호출하지만 일관성없고 신뢰할 수없는 테스트를 수행합니다. 그래서 여기에 우리는 그것을 밖으로 stub.

스파이가있는 단위 테스트 (상호 작용 테스트)

클래식 유닛은 테스트 상태를 테스트하지만, 동작이 상태를 통해 다른 클래스에 의존하는 메소드를 적절하게 테스트하는 것은 불가능할 수 있습니다. 상호 작용 테스트를 통해 이러한 방법을 테스트합니다.이 테스트는 테스트중인 시스템이 공동 작업자를 올바르게 호출하는지 확인합니다. 공동 작업자는 자체 단위 테스트가 있기 때문에 테스트 된 메서드의 실제 책임에 대한 테스트로 충분합니다. 우리는이 메소드가 주어진 특정 결과를 리턴하지만 그 대신에 그것의 협력자를 정확하게 호출하는지 테스트하지 않습니다.

// Test that squareOfDouble invokes square() with the doubled value

let systemUnderTest = new Calculator()          // Arrange - setup environment
let square = spy()
systemUnderTest.setSquare(square)               //   inject a spy

let actual = systemUnderTest.squareOfDouble(3)  // Act - Call system under test

assert(square.calledWith(6))                    // Assert - Validate expected interaction

간단한 Java + JUnit 테스트

JUnit 은 Java 코드 테스트에 사용되는 주요 테스트 프레임 워크입니다.

테스트중인 클래스는 간단한 은행 계좌를 모델링합니다.이 계좌는 초과 인출시 벌칙을 부과합니다.

public class BankAccount {
    private int balance;

    public BankAccount(int i){
        balance = i;
    }

    public BankAccount(){
        balance = 0;
    }

    public int getBalance(){
        return balance;
    }

    public void deposit(int i){
        balance += i;
    }

    public void withdraw(int i){
        balance -= i;
        if (balance < 0){
            balance -= 10; // penalty if overdrawn
        }
    }
}

이 테스트 클래스는 일부 BankAccount 공용 메소드의 동작을 검증합니다.

import org.junit.Test;
import static org.junit.Assert.*;

// Class that tests
public class BankAccountTest{

    BankAccount acc;

    @Before                        // This will run **before** EACH @Test
    public void setUptestDepositUpdatesBalance(){
        acc = new BankAccount(100);  
    } 

    @After                        // This Will run **after** EACH @Test
    public void tearDown(){
    // clean up code
    }

    @Test
    public void testDeposit(){
       // no need to instantiate a new BankAccount(), @Before does it for us

        acc.deposit(100);

        assertEquals(acc.getBalance(),200); 
    }

    @Test
    public void testWithdrawUpdatesBalance(){    
        acc.withdraw(30);

        assertEquals(acc.getBalance(),70); // pass
    }

    @Test
    public void testWithdrawAppliesPenaltyWhenOverdrawn(){

        acc.withdraw(120);

        assertEquals(acc.getBalance(),-30);
    }
}

NUnit 및 C #을 사용하여 매개 변수가있는 단위 테스트

using NUnit.Framework;

namespace MyModuleTests 
{
    [TestFixture]
    public class MyClassTests
    {
        [TestCase(1, "Hello", true)]
        [TestCase(2, "bye", false)]
        public void MyMethod_WhenCalledWithParameters_ReturnsExpected(int param1, string param2, bool expected)
        {
        //Arrange
        var foo = new MyClass(param1);

        //Act
        var result = foo.MyMethod(param2);

        //Assert
        Assert.AreEqual(expected, result);
        }
    }
}

기본적인 파이썬 단위 테스트

import unittest

def addition(*args):
    """ add two or more summands and return the sum """

    if len(args) < 2:
        raise ValueError, 'at least two summands are needed'
    
    for ii in args: 
        if not isinstance(ii, (int, long, float, complex )):
            raise TypeError

    # use build in function to do the job
    return sum(args) 

이제 테스트 부분 :

class Test_SystemUnderTest(unittest.TestCase):

    def test_addition(self):
        """test addition function"""

        # use only one summand - raise an error 
        with self.assertRaisesRegexp(ValueError, 'at least two summands'):
            addition(1)
        
        # use None - raise an error
        with self.assertRaises(TypeError):
            addition(1, None)
        
        # use ints and floats 
        self.assertEqual(addition(1, 1.), 2)

        # use complex numbers
        self.assertEqual(addition(1, 1., 1+2j), 3+2j)

if __name__ == '__main__':
    unittest.main()

매개 변수가있는 XUnit 테스트

using Xunit;

public class SimpleCalculatorTests
{
    [Theory]
    [InlineData(0, 0, 0, true)]
    [InlineData(1, 1, 2, true)]
    [InlineData(1, 1, 3, false)]
    public void Add_PassMultipleParameters_VerifyExpected(
        int inputX, int inputY, int expected, bool isExpectedCorrect)
    {
        // Arrange
        var sut = new SimpleCalculator();

        // Act
        var actual = sut.Add(inputX, inputY);

        // Assert
        if (isExpectedCorrect)
        {
            Assert.Equal(expected, actual);
        }
        else
        {
            Assert.NotEqual(expected, actual);
        }
    }
}

public class SimpleCalculator
{
    public int Add(int x, int y)
    {
        return x + y;
    }
}


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow