블랙박스 테스팅 :
소프트웨어의 내부 구조나 동작 원리를 모르는 상태에서, 사용자의 입장에서 동작을 검사하는 방법입니다. 이러한 방식의 테스팅은 다음과 같은 장점과 단점을 가지고 있습니다.

  • 장점:누구나 테스트를 수행할 수 있습니다. 개발자뿐만 아니라 디자이너, 베타 테스터, 관리자 등 누구나 소프트웨어의 동작을 검사할 수 있습니다.
  • 단점:기능이 증가할수록 테스트의 범위가 증가합니다. 새로운 기능이 추가될 때마다 해당 기능을 테스트해야 하므로 테스트의 양이 계속해서 증가할 수 있습니다.테스트를 수행하는 사람에 따라 테스트 품질이 다를 수 있습니다. 테스트하는 사람의 능력과 경험에 따라 테스트의 정확성과 완전성이 달라질 수 있습니다. 이러한 이유로 QA(Quality Assurance) 직군이 필요한 이유도 있습니다.

개발자 테스트 : 

개발자가 작성한 코드를 검증하기 위해 테스트 코드를 작성합니다. 코드의 예상 동작과 실제 동작을 비교하여 테스트를 수행합니다.

장점:

  • 빠르고 정확한 테스트가 가능합니다. 테스트 코드를 실행하여 예상한 결과와 실제 결과를 비교함으로써 결함을 빠르게 발견할 수 있습니다.
  • 테스트 자동화가 가능합니다. 테스트 코드를 자동으로 실행하여 동작을 검증할 수 있으며, 배포 시 자동화된 테스트가 동작을 검증하는 데 도움이 됩니다.
  • 리팩토링이나 기능 추가 시 편리합니다. 테스트 코드가 있으면 코드 변경에 따른 영향을 빠르게 파악하여 수정할 수 있습니다.

단점:

  • 개발 시간이 더 오래 걸립니다. 테스트 코드를 작성하는 데에는 추가적인 노력과 시간이 필요합니다.
  • 테스트 코드를 유지보수해야 합니다. 코드 변경에 따라 테스트 코드도 함께 수정해야 하므로 유지보수 비용이 증가할 수 있습니다.

단위 테스트 (Unit Test):

개별 모듈 또는 함수 단위로 테스트를 수행합니다. 모듈 내부의 세부 로직과 동작을 검증합니다.

개발 초기 단계부터 개별 모듈을 테스트하며, 빠르게 실행하고 결함을 발견하는 데 유용합니다.

장점:

  • 세밀한 부분까지 테스트가 가능합니다. 모듈의 각각의 기능을 개별적으로 확인하여 결함을 찾을 수 있습니다.
  • 코드 일관성과 안정성을 높일 수 있습니다. 각 모듈이 독립적으로 동작하면서 예상한 대로 작동하는지 확인할 수 있습니다.

단점:

  • 모듈 간의 상호작용을 검증할 수 없습니다. 모듈 간의 연결과 상호작용에서 발생하는 오류를 찾기 어렵습니다.

통합 테스트 (Integration Test):

두 개 이상의 모듈을 연결하여 테스트합니다. 모듈 간의 상호작용과 통합에서 발생하는 오류를 검증합니다.

모듈 간의 상호작용이 복잡하고 중요한 시스템에서 사용되며, 시스템 전체적인 동작을 확인합니다.

장점:

  • 모듈 간의 연결에서 발생하는 에러를 검증할 수 있습니다. 여러 모듈이 함께 동작할 때 발생하는 문제를 찾아낼 수 있습니다.

단점:

  • 테스트 코드 작성이 복잡하고 어려울 수 있습니다. 여러 모듈을 연결하고 상호작용을 검증해야 하기 때문에 테스트 코드 작성이 복잡해질 수 있습니다.
  • 테스트 시나리오의 다양성에 대한 처리가 어렵습니다. 다양한 상황과 조건을 고려하여 테스트를 수행하기 어려울 수 있습니다.

E2E 테스트 (End-to-End Test):

실제 사용자의 관점에서 전체 시스템을 테스트합니다. 사용자의 흐름에 따라 실제 환경에서 애플리케이션이 예상대로 동작하는지 검증합니다.
실제 사용자 경험을 반영하고, 시스템의 완전한 동작을 검증하는데 사용됩니다. 다만, 구축과 유지보수가 복잡하며 시간이 많이 소요될 수 있습니다.

장점:

  • 실제 사용자 환경에서 테스트하기 때문에 실제 상황을 재현할 수 있습니다. 다양한 플랫폼, 단말기, 네트워크 등 다양한 환경에서의 동작을 확인할 수 있습니다.
  • 사용자의 관점에서 테스트하기 때문에 사용자 경험을 중심으로 평가할 수 있습니다.

단점:

  • 다양한 테스트 환경 구성이 어렵습니다. 다양한 단말기, 운영체제, 브라우저 등 다양한 조합에 대한 테스트를 구성하기 어려울 수 있습니다.
  • 테스트 시나리오가 복잡해질 수 있습니다. 사용자 흐름에 따라 다양한 시나리오를 작성하고 관리해야 하므로 테스트 코드 작성이 복잡해질 수 있습니다.

 

단위 테스트 코드 작성 시의 장점과 단점 : 

장점:

  1. 결함을 빨리 찾을 수 있습니다: 단위 테스트 코드는 코드 일부분을 실행하여 오류를 찾아낼 수 있습니다. 따라서 결함을 빨리 찾을 수 있으며 빠르게 수정할 수 있습니다.
  2. 코드 품질 향상: 단위 테스트 코드는 소프트웨어의 코드 품질을 향상시키는 데 도움이 됩니다. 테스트 코드를 작성하면 코드가 보다 정확하고 일관성 있게 작성됩니다.
  3. 유지보수성 개선: 단위 테스트 코드는 코드 변경에 대한 영향도를 파악하며, 변경이 필요한 부분을 빠르게 파악하여 수정할 수 있습니다. 이는 유지보수성을 높이는 데에 큰 도움이 됩니다.
  4. 문서화: 단위 테스트 코드는 코드를 문서화하는 데에도 도움이 됩니다. 각 테스트 케이스는 코드의 사용 예제가 될 수 있으며, 이를 통해 코드 사용 방법을 쉽게 이해할 수 있습니다.

단점:

  1. 추가 작업이 필요합니다: 단위 테스트 코드를 작성하는 데에는 추가적인 노력이 필요합니다. 코드 자체를 작성하는 이외에도 코드 조각에 대한 테스트 케이스를 작성해야 합니다.
  2. 테스트 케이스가 모든 오류를 포착하지 못할 있습니다: 모든 상황을 대비한 테스트 케이스를 작성하기 어렵기 때문에, 단위 테스트는 모든 오류를 포착하지 못할 있습니다.
  3. 작성 비용이 높을 있습니다: 대규모 프로젝트에서는 수많은 단위 테스트 케이스를 작성해야 하므로, 작성 비용이 높아질 있습니다.
  4. 유지보수 비용이 높을 있습니다: 코드 변경 시에는 테스트 케이스도 수정해야 하므로, 유지보수 비용이 높아질 있습니다.

 

TDD(Test-Driven Development)와 BDD(Behavior-Driven Development) :

소프트웨어 개발 방식 중 하나로, 테스트 중심의 개발 프로세스를 강조하지만, 접근법은 약간 다릅니다.
TDD는 코드 수준에서의 테스트 중심 개발이라면, BDD는 시스템의 동작 및 비즈니스 요구사항에 초점을 맞춘 테스트 중심 개발입니다.

TDD (Test-Driven Development) : 

TDD는 작은 단위의 테스트를 먼저 작성하고, 이 테스트를 통과할 수 있도록 코드를 작성하는 방식입니다. 이 방식의 목표는 요구사항이 변경되거나 추가되더라도 소프트웨어의 품질을 유지하는 것입니다.

TDD의 일반적인 절차는 다음과 같습니다:

  1. 먼저 실패하는 단위 테스트를 작성합니다.
  2. 테스트를 통과할 수 있도록 충분한 코드를 작성합니다.
  3. 작성된 코드를 리팩토링합니다.

BDD (Behavior-Driven Development) : 

BDD는 TDD의 한 종류로 볼 수 있지만, BDD는 시스템의 동작에 중점을 둡니다. BDD는 비개발자(예: 비즈니스 분석가, 이해당사자 등)와 개발자가 협업할 수 있도록 테스트 케이스를 자연어 스타일로 작성하는 것을 강조합니다.

BDD의 주요 절차는 다음과 같습니다:

  1. 예상되는 행동에 대해 테스트를 작성합니다. 이는 비즈니스 요구사항을 기반으로 하며, 주로 사용자 스토리와 같은 형식을 사용합니다.
  2. 해당 행동을 구현할 수 있도록 코드를 작성합니다.
  3. 코드를 리팩토링합니다.

결국, TDD BDD 모두 테스트 중심의 개발을 추구하지만, BDD 시스템의 행동에 중점을 두고 비개발자와의 협업을 강조하며, TDD 개발자가 테스트를 기반으로 코드를 작성하도록 강조합니다. 사이의 선택은 프로젝트의 요구사항, 팀의 선호도, 그리고 소프트웨어의 복잡성 등에 따라 달라질 있습니다.

더보기

코드를 먼저 작성하고 테스트를 나중에 하는 접근법은 TDD BDD와는 반대되는 방향입니다. 이런 방식은 코드의 품질을 보장하기 어렵고, 나중에 문제가 발생했을  이를 찾고 수정하는   많은 시간과 노력이 필요하게 됩니다. 따라서 가능하면 TDD BDD 같은 테스트 중심의 개발 방식을 적용하는 것이 좋습니다.

기능을 먼저 구현하고 그 후에 테스트 코드를 작성하는 접근법을 "테스트-후(Test-Last)" 개발 또는 "전통적인" 개발 방법이라고 부릅니다. 이 방법은 전통적인 소프트웨어 개발 프로세스에서 일반적으로 볼 수 있습니다.

이런 접근법에서는 개발자가 요구사항에 따라 기능을 먼저 개발하고, 그 후에 해당 기능을 검증하는 테스트 케이스를 작성합니다. 이 방식의 단점은 코드가 작성된 후에만 테스트가 가능하다는 것이며, 따라서 버그를 일찍 찾아내는 것이 더 어려울 수 있습니다.

반면에, TDD(Test-Driven Development) BDD(Behavior-Driven Development) 같은 테스트-먼저(Test-First) 접근법에서는 테스트 케이스를 먼저 작성하고,  테스트 케이스를 통과하는 코드를 작성합니다.  접근법의 장점은 테스트를 통해 요구사항을 명확히 정의하고, 즉시 피드백을 받을  있다는 것입니다.

  1. 프로젝트의 특성: TDD나 BDD는 많은 이점을 제공하지만, 모든 프로젝트에 적합한 것은 아닙니다. 예를 들어, 프로젝트 요구사항이 자주 변경되지 않고, 프로젝트의 복잡성이 낮을 경우, 전통적인 개발 방법을 사용하는 것이 더 효율적일 수 있습니다.
  2. 팀의 경험과 역량: 팀원들이 TDD나 BDD에 익숙하지 않다면, 이러한 접근법을 도입하는 데 시간과 노력이 필요할 수 있습니다. 이런 경우, 팀의 경험과 역량을 최대한 활용하여 전통적인 개발 방법을 사용하는 것이 더 합리적일 수 있습니다.
  3. 시간 제약: 테스트 주도 개발은 초기에 투자해야 하는 시간이 더 많습니다. 이런 접근법은 장기적으로는 높은 품질의 코드와 유지 관리의 용이성을 제공하지만, 단기적으로는 개발 시간이 늘어날 수 있습니다. 따라서, 시간 제약이 있는 프로젝트에서는 전통적인 개발 방법을 선택할 수 있습니다.

 

테스트 코드를 작성하는 가장 대표적인 방법론 : Given - 준비 When - 실행 Then - 검증

이 방법론은 행동 주도 개발(BDD)에서 널리 사용되는 테스트 패턴입니다.

  • Given: 테스트의 사전 조건을 설정합니다. 이는 테스트가 진행될 환경이나 상태를 의미합니다.
  • When: 테스트의 주체가 특정 행동을 실행하는 단계입니다.
  • Then: When 단계에서의 행동이 주어진 사전 조건(Given) 하에서 예상한 결과를 나타내는지 검증하는 단계입니다.

JUnit : 

JUnit 자바에서 가장 널리 사용되는 테스트 프레임워크로, 개발자가 쉽게 단위 테스트를 작성하고 실행할 있게 도와줍니다. 테스트 케이스는 서로 독립적으로 작성되어야 하며, 이러한 원칙은 테스트의 견고성과 신뢰성을 보장합니다.

 

이상적으로, 각 테스트 케이스는 서로 분리되어야 한다. 이를 위해 가짜 객체(Mock object)를 생성하는 것도 좋은 방법이다.

 

Mock Object :

Mock 객체는 테스트에서 실제 객체의 역할을 대체합니다. Mock 객체를 사용하면 외부 시스템에 의존하지 않고 테스트를 수행할 수 있습니다. 예를 들어, 데이터베이스나 네트워크와 같은 외부 시스템과의 상호작용을 모방할 수 있습니다.

Mock 객체를 만들려면 일반적으로 해당 객체를 구현하는 인터페이스나 클래스를 직접 생성해야 합니다. 경우 모든 메소드의 동작을 직접 구현하거나 오버라이드해야 하므로, 복잡한 객체를 mocking 경우 상당히 번거로울 있습니다.

  • 실제 객체와 겉만 같은 객체입니다. 동일한 클래스명, 함수명
  • 실제 DB 작업은 하지 않습니다.

Mockito :

Mockito 자바에서 가장 널리 사용되는 mocking 프레임워크 하나입니다. Mockito 사용하면 실제 객체 대신 Mock 객체를 쉽게 생성하고, 행동을 정의하고, 검증할 있습니다. 이를 통해 개발자는 시스템의 다른 부분과 독립적으로 특정 부분을 테스트할 있습니다.