보라코딩
Day 19, C# _ Unit Test 본문
단위테스트
- 애플리케이션 안에 있는 개별적인 코드 단위가 의도한 대로 작동하는지 확인하는 행위
- 개별적인 기능이 의도한대로 작동하는지 확인하는 행위
단위테스트 사용하는 이유
- 원하는 부분만 테스트해서 결과를 빠르게 볼 수 있음
- 리팩토링을 안정적으로 가능
- 단위테스트 실패 지점에서 코드의 문제점 빠르게 찾을 수 있음
테스트코드 작성 표현방식 (선택)
- given - when -then 패턴
- given : 테스트를 위해 준비하는 과정 / 테스트에 사용하는 값 정의
- when : 테스트하고자 하는 기능 실행
- then : 기능 실행 후 결과를 검증
@Test
@Displayname("자동차는 명령을 받은만큼 이동거리가 증가한다")
void car_moves_as_order(){
// given (주어진 값)
int orderCount = 10;
Car car = new Car();
// when (기능 작동)
car.moveAsOrdered(orderedCount);
int distanceResult = car.getPosition();
// then (기능 작동 후 검증)
assertThat(distanceResult).isEqualTo(orderCount);
단위테스트 꿀팁
@ParameterizedTest
사용해서 여러 값을 테스트하자!
@ParameterizedTest
@ValueSource(ints = {-1, 0, 11, 12}
@DisplayName("자동차 이동")
void throws_exception_when_order_count_invalid(int givenOrderCount){
// given
String exceptedErrorMessage = "이동 거리는 1 이상 10 이하의 수만 가능";
Car car = new Car();
// when & then
assertThatThrownBy(() -> car.moveAsOrdered(givenOrderCount)
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining(expectedErrorMessage);
First 원칙
- 효율적이고 좋은 단위 테스트를 위한
5가지 요소로 이뤄진 규칙
- Fast : 단위테스트는 빨라야 한다.
- Independent : 테스트는 독립적으로 동작해야 한다. 이전 테스트에 영향을 받으면 실패 원인을 찾기 어렵다.
- Repeatable : 어떤 상황에서든 예상한 대로 테스트 결과가 나와야한다.
- Self-Validating : 출력 혹은 로그가 아닌 테스트 자체적으로 결과가 나와야한다.
- Timely : 적시에 테스트를 철저하게 작성해야한다.
TDD(Test Driven Development) : 테스트 주도 개발
- 수정 요청 시, 리팩토링을 훨씬 안정적으로 할 수 있음
- 스펙 문서 기능 (파라미터, 반환값 등 스펙 확인)
- 디자인 개선 효과
- 디버깅 시간 감소
- 프로젝트 생산성 향샹 (비지니스 로직의 허점을 사전에 발견)
테스트코드 실습
Reservation.cs
namespace TestNinja.Fundamentals
{
public class Reservation
{
public User MadeBy { get; set; }
public bool CanBeCancelledBy(User user)
{
return (user.IsAdmin || MadeBy == user);
}
}
public class User
{
public bool IsAdmin { get; set; }
}
}
ReservationTests.cs
using TestNinja.Fundamentals;
namespace TestNinja.UnitTests
{
public class ReservationTests
{
[SetUp]
public void Setup()
{
}
[Test]
public void CanBeCancelledBy_Scenario_ExpectedBehavior()
{
// Arrange
var reservation = new Reservation();
// Act
var result = reservation.CanBeCancelledBy(new User { IsAdmin = true });
// Assert
Assert.IsTrue(result);
}
[Test]
public void CanBeCancelledBy_SameUserCancellingTheReservation()
{
var user = new User();
var reservation = new Reservation { MadeBy = user };
var result = reservation.CanBeCancelledBy(user);
Assert.IsTrue(result);
}
[Test]
public void CanBeCacelledBy_AnotherUserCancellingReservation_ReturnFalse()
{
var reservation = new Reservation { MadeBy = new User() };
var result = reservation.CanBeCancelledBy(new User());
Assert.IsFalse(result);
}
}
}
계산기 테스트코드 작성하기
Calculator.cs
using System;
using System.Collections.Generic;
namespace TestNinja.Fundamentals
{
public class Calculator
{
public int Add(int a, int b)
{
return a + b;
}
public int Subtract(int a, int b)
{
return a - b;
}
public int Multiply(int a, int b)
{
return a * b;
}
public int Divide(int a, int b)
{
if (b == 0)
throw new ArgumentException("Divisor cannot be zero.");
return a / b;
}
}
}
CalculatorTests.cs
using NUnit.Framework.Constraints;
using TestNinja.Fundamentals;
namespace TestNinja.UnitTests
{
public class CalculatorTests
{
[SetUp]
public void Setup()
{
}
[Test] // 더하기
public void Plus()
{
// Arrange
int a = 2; int b = 3;
// Act
Calculator calculator = new Calculator();
int result = calculator.Add(a, b);
// Assert
Assert.AreEqual(5, result);
}
[Test] // 빼기
public void Substract()
{
// Arrange
int a = 5; int b = 3;
// Act
Calculator calculator = new Calculator();
int result = calculator.Subtract(a, b);
// Assert
Assert.AreEqual(2, result);
}
[Test] // 곱하기
public void Multiply()
{
// Arrange
int a = 2; int b = 3;
// Act
Calculator calculator = new Calculator();
int result = calculator.Multiply(a, b);
// Assert
Assert.AreEqual(6, result);
}
[Test] // 나누기
public void Divide()
{
// Arrange
int a = 6; int b = 3;
// Act
Calculator calculator = new Calculator();
int result = calculator.Divide(a, b);
// Assert
Assert.AreEqual(2, result);
}
[Test] // 0으로 나누기
public void DivideByZero()
{
// Arrange
int a = 5; int b = 0;
// Act
Calculator calculator = new Calculator();
// Assert
Assert.Throws<ArgumentException>(() => calculator.Divide(a, b));
}
[Test] // 음수 빼기
public void Subtrict_minus()
{
// Arrange
int a = -1; int b = -2;
// Act
Calculator calculator = new Calculator();
int result = calculator.Subtract(a, b);
// Assert
Assert.AreEqual(1, result);
}
[Test] // 0 곱하기
public void MultiplyByZero()
{
// Arrange
int a = 811; int b = 0;
// Act
Calculator calculator = new Calculator();
int result = calculator.Multiply(a, b);
// Assert
Assert.AreEqual(0, result);
}
[Test] // 복잡한 계산
public void ComplicatedCalculator()
{
// Arrange
int a = 2; int b = 3; int c = 4;
// Act
Calculator calculator = new Calculator();
int result1 = calculator.Multiply(a, b);
int result2 = calculator.Divide(c, a);
int result3 = calculator.Subtract(result1, result2);
// Assert
Assert.AreEqual(4, result3);
}
}
}
'개발자가 되었다?' 카테고리의 다른 글
Day 21, EF Core (0) | 2023.09.13 |
---|---|
Day 20, C# (0) | 2023.09.12 |
Day 18, C# (DB 연동_MySQL) (0) | 2023.09.08 |
Day 17, C# (WPF로 카카오 API 연동) (0) | 2023.09.07 |
Day 16, C# (0) | 2023.09.07 |