자동화된 테스트란?

완료됨

이 단원에서는 자동화된 테스트의 이점 및 수행할 수 있는 테스트의 종류에 대해 알아봅니다. 또한 적합한 테스트를 만드는 요인에 대해 알아보고, 사용할 수 있는 몇 가지 테스트 도구를 살펴봅니다.

자동화된 테스트란?

자동화된 테스트는 소프트웨어를 사용하여 코드를 실행하고 실제 결과와 예상한 결과를 비교합니다. 이를 탐색적 또는 수동 테스트와 비교합니다. 여기서 인간은 일반적으로 소프트웨어가 예상대로 작동하는지 확인하기 위해 테스트 계획의 지침을 따릅니다.

수동 테스트에는 이점이 있습니다. 그러나 코드 베이스의 크기가 커짐에 따라 모든 기능(에지 사례 포함)을 수동으로 테스트하는 것은 반복적이고 지루하며 오류가 발생하기 쉽습니다. 자동화된 테스트를 통해 이러한 부담을 어느 정도 해소하고 수동 테스터는 가장 잘하는 작업에 집중할 수 있으므로 사용자는 소프트웨어에 대해 긍정적인 경험을 할 수 있습니다.

테스트 피라미드

자동화된 테스트에 대해 생각할 때 테스트를 레이어로 분리하는 것이 일반적입니다. Mike Cohn은 테스트 피라미드로 알려진 이 개념을 자신의 저서 Succeeding with Agile에서 제안합니다.

Diagram showing the test pyramid. The pyramid shows the unit test layer marked with callout 1, and UI layer tests marked with callout 2.

위 테스트 피라미드는 Cohn 모델의 단순한 버전이지만, 해당 개념은 개발자가 함수, 클래스, 메서드와 같은 소프트웨어의 기본 수준(피라미드의 설명선 1)을 확인하는 테스트를 작성하는 데 대부분의 노력을 집중하며, 사용자 인터페이스, 즉 UI 레이어(피라미드의 설명선 2)에서와 같이 기능이 결합되면 점차적으로 노력이 줄어든다는 점을 보여 줍니다. 이 견해는 각 하위 수준 구성 요소가 격리 상태에서 예상대로 작동하는지 확인할 수 있는 경우 상위 수준의 테스트에서는 여러 구성 요소가 함께 작동하여 예상된 결과를 얻는지 확인하기만 하면 된다는 것입니다.

언제 테스트를 작성해야 하나요?

정답은 주로 테스트 작성 시 사용자의 필요와 경험에 따라 다릅니다.

이미 작성하고 배포한 코드에 대한 테스트를 추가하는 것은 결코 늦은 것이 아닙니다. 이는 특히 자주 손상되거나 테스트 팀의 노력이 가장 많이 필요한 기능에 해당됩니다.

테스트를 연속 통합 및 지속적인 업데이트 파이프라인과 관련하여 이야기할 때 듣게 될 두 가지 개념은 ‘지속적인 테스트’ 및 ‘왼쪽 시프트’입니다.

지속적인 테스트는 모든 변화가 파이프라인을 통해 이동함에 따라 개발 프로세스 초기에 테스트가 실행됨을 의미합니다. 왼쪽 시프트란 개발 프로세스 초기에 소프트웨어 품질과 테스트를 고려하는 것을 의미합니다.

예를 들어 개발자들은 변경 사항을 파이프라인에 제출하기 전에 기능을 개발하고 전체 테스트 도구 모음을 실행할 때 흔히 테스트 사례를 추가합니다. 해당 접근 방식은 개발자가 빌드 중인 기능이 예상대로 동작하고 기존 기능을 중단시키지 않도록 하는 데 도움이 됩니다.

다음은 Microsoft의 Cloud Advocate인 Abel Wang이 DevOps 플랜에서 품질을 유지하는 방법을 설명하는 짧은 비디오입니다.

Abel에게 질문하기

왼쪽 시프트 시 테스터는 기능에 대한 코드가 작성되기도 전에 설계 프로세스에 참여해야 하는 경우가 많습니다. 이를 “핸드오프” 모델과 비교해 보겠습니다. 해당 모델에서는 소프트웨어가 설계 및 작성된 후에야 ​​테스트할 새로운 기능을 테스트 팀에 제공합니다. 프로세스에서 늦게 발견된 버그는 팀의 배달 일정에 영향을 줄 수 있으며, 개발자가 이 기능을 처음 빌드한 후 몇 주 또는 몇 달 후에 버그가 발견될 수도 있습니다.

단점은 다음과 같습니다.

자동화된 테스트를 사용하면 장단점이 따라옵니다. 자동화된 테스트를 사용하면 테스터가 최종 사용자 환경을 검증하는 데 시간을 집중할 수 있지만, 개발자들은 테스트 코드를 작성하고 유지하는 데 더 많은 시간을 할애해야 할 수 있습니다.

그러나 자동화된 테스트의 핵심은 테스터가 최고 품질의 코드, 즉 예상대로 작동하는 것으로 입증된 코드만 받도록 보장하는 데 있습니다. 따라서 개발자는 더 적은 버그를 처리하거나 원래 고려하지 않았던 에지 케이스로 인한 코드 재작성을 방지함으로써 시간을 어느 정도 절약할 수 있습니다.

추가 혜택

자동화된 테스트의 추가적인 두 가지 이점은 문서화와 코드를 더 쉽게 리팩터링할 수 있는 기능입니다.

설명서

수동 테스트 계획을 소프트웨어가 어떻게 동작해야 하고 특정 기능이 존재하는 이유에 관해 문서 유형으로 사용할 수 있다.

자동화된 테스트를 동일한 목적으로 사용할 수 있습니다. 자동화된 테스트 코드는 종종 사람이 읽을 수 있는 형식을 사용합니다. 사용자가 제공하는 입력 세트는 사용자가 입력할 수 있는 값을 나타냅니다. 관련된 각 출력은 사용자가 예상하는 결과를 지정합니다.

실제로 많은 개발자가 새로운 기능을 구현하기 전에 테스트 코드를 작성하여 TDD(테스트 기반 개발) 방법을 따릅니다. 이 개념은 초기에 실패하는 사양이라고 하는 테스트 세트를 작성하는 것입니다. 그런 다음 개발자는 모든 테스트가 통과할 때까지 기능을 구현하기 위해 코드를 점진적으로 작성합니다. 사양은 요구 사항을 문서화할 뿐만 아니라, TDD 프로세스를 통해 기능을 구현하기 위해 필요한 양의 코드만 작성할 수 있습니다.

리팩터링

특정 부분이 더 빨리 실행되도록 리팩터링하려는 대형 코드 베이스가 있다고 가정해 보겠습니다. 리팩터링으로 인해 애플리케이션의 일부가 손상되지 않을 것임을 어떻게 알까요?

자동화된 테스트는 계약의 형식으로 제공됩니다. 즉, 입력 및 예상 결과를 지정합니다. 통과된 테스트의 세트가 있는 경우 코드를 실험하고 리팩터링하는 게 더 쉽습니다. 변경하는 경우 테스트를 실행하고 계속 통과하는지 확인하기만 하면 됩니다. 리팩터링 목표를 달성한 후에는 변경 사항을 빌드 파이프라인에 제출할 수 있습니다. 그러면 모든 사람이 손상의 위험이 낮아진 상태로 혜택을 누릴 수 있습니다.

어떤 유형의 자동화된 테스트가 있나요?

자동화된 테스트에는 여러 가지 유형이 있습니다. 각 테스트는 별도의 목적으로 제공됩니다. 예를 들어 인증된 사용자만 소프트웨어 또는 해당 기능 중 하나에 액세스할 수 있는지 확인하기 위해 보안 테스트를 실행할 수 있습니다.

연속 통합 및 빌드 파이프라인을 이야기할 때 일반적으로 ‘개발 테스트’를 언급합니다. 개발 테스트란 애플리케이션을 테스트 또는 프로덕션 환경에 배포하기 전에 실행할 수 있는 테스트를 말합니다.

예를 들어 정적 코드 분석의 한 형태인 lint 테스트는 소스 코드를 검사하여 해당 코드가 팀의 스타일 가이드를 준수하는지 여부를 확인합니다. 일관된 형식의 코드는 모두가 보다 쉽게 읽고 유지 관리할 수 있습니다.

이 모듈에서는 단위 테스트코드 검사 테스트를 사용하여 작업하겠습니다.

단위 테스트는 개별 함수 또는 메서드와 같은 프로그램 또는 라이브러리의 가장 기본적인 구성 요소를 검사합니다. 예상 결과와 함께 하나 이상의 입력을 지정합니다. Test Runner는 각 테스트를 수행하고 실제 결과와 예상 결과가 일치하는지 확인합니다.

예를 들어 나누기가 포함된 산술 연산을 수행하는 함수가 있는 경우 사용자가 0 및 -1과 같은 에지 케이스 값과 함께 입력할 것으로 예상하는 값을 몇 가지 지정할 수 있습니다. 특정 입력이 오류나 예외를 생성하는 경우 함수가 동일한 오류를 생성하는지 확인할 수 있습니다.

코드 검사 테스트는 단위 테스트가 적용된 코드의 비율을 컴퓨팅합니다. 코드 검사 테스트는 함수가 완전히 적용되도록 코드에 조건부 분기를 포함할 수 있습니다.

코드 검사 비율이 클수록 나중에 완전히 테스트되지 않은 코드에 버그가 없을 것임을 확신할 수 있습니다. 100% 코드 검사에 도달할 필요는 없습니다. 실제로, 시작할 때는 비율이 낮다는 것을 알게 될 가능성이 높지만 이는 문제가 있거나 자주 사용되는 코드를 다루는 추가적인 테스트를 더할 수 있는 시작점이 됩니다.

단위 테스트 격리 유지

단위 테스트에 대해 학습할 때 ‘모의’, ‘스텁’, ‘종속성 주입’과 같은 용어를 사용하게 됩니다.

단위 테스트는 여러 구성 요소가 상호 작용하는 방식이 아닌 개별 함수 또는 메서드를 확인해야 한다는 점을 기억하세요. 그런데 데이터베이스나 웹 서버를 호출하는 함수가 있다면 어떻게 처리해야 할까요?

외부 서비스를 호출하면 격리가 중단될 뿐만 아니라 속도가 느려질 수 있습니다. 데이터베이스 또는 웹 서버가 다운되거나 달리 사용할 수 없는 경우 호출로 인해 테스트 실행이 중단될 수도 있습니다.

모의 및 종속성 주입과 같은 기법을 사용하면 해당 외부 기능을 모방하는 구성 요소를 만들 수 있습니다. 이 모듈의 뒷부분에 예제가 나와 있습니다.

나중에 통합 테스트를 실행하여 애플리케이션이 실제 데이터베이스 또는 웹 서버와 올바르게 작동하는지 확인할 수 있습니다.

무엇이 좋은 테스트를 만드는가?

고유한 자체 테스트를 작성하고 다른 사람이 작성한 테스트를 읽는 경험을 쌓으면 좋은 테스트를 더 잘 식별할 수 있게 됩니다. 다음은 시작을 위한 몇 가지 지침입니다.

  • 테스트를 위한 테스트하지 않기: 테스트는 목적에 부합해야 합니다. 검사 목록 항목을 지우기 위해 하는 것이 아닙니다. 중요한 코드가 의도한 대로 작동하고 기존 기능을 중단시키지 않는지 확인하는 테스트를 작성해야 합니다.
  • 테스트를 짧게 유지: 테스트는 최대한 빨리 완료되어야 합니다. 특히 개발 및 빌드 단계에서 수행하는 테스트는 더욱더 그러합니다. 각 변경 사항이 파이프라인에 적용되는 동안 테스트가 실행될 때 해당 테스트가 병목 상태가 되어서는 안 됩니다.
  • 테스트가 반복 가능한지 확인: 테스트를 개발자 컴퓨터에서 실행하든, 동료 컴퓨터에서 실행하든 또는 빌드 파이프라인에서 실행하든 관계없이 테스트 실행이 매번 동일한 결과를 생성해야 합니다.
  • 테스트 집중 유지: 일반적인 오해는 테스트가 다른 사람이 작성한 코드를 다루기 위한 것이라 점입니다. 일반적으로 테스트는 자신의 코드에만 적용되어야 합니다. 예를 들어 프로젝트에서 오픈 소스 그래픽 라이브러리를 사용하는 경우 해당 라이브러리를 테스트할 필요는 없습니다.
  • 적절한 세분성 선택: 예를 들어 단위 테스트를 수행하는 경우 개별 테스트는 여러 함수 또는 메서드를 결합하거나 테스트해서는 안 됩니다. 각 함수를 개별적으로 테스트한 후에, 여러 구성 요소가 제대로 상호 작용하는지 확인하는 통합 테스트를 작성합니다.

어떤 유형의 테스트 도구를 사용할 수 있나요?

사용하는 테스트 도구는 빌드 중인 애플리케이션 유형 및 수행하려는 테스트 유형에 따라 달라집니다. 예를 들어 여러 유형의 웹 브라우저 및 운영 체제에서 UI 테스트를 수행하는 데 Selenium을 사용할 수 있습니다.

애플리케이션을 작성한 언어가 무엇이든 관계없이 다양한 테스트 도구를 사용할 수 있습니다.

예를 들어 Java 애플리케이션의 경우, lint 테스트를 수행하려면 Checkstyle을, 단위 테스트를 수행하려면 JUnit을 선택할 수 있습니다.

이 모듈에서는 .NET 커뮤니티에서 널리 사용되므로 단위 테스트에 NUnit을 사용합니다.

지식 점검

1.

테스트 피라미드에 따르면 테스트를 실행하면서 대부분의 시간을 어디에 할애해야 하나요?

2.

왼쪽 시프트는 다음을 말합니다.

3.

다음 중 가장 좋은 테스트 사례를 설명한 것은 무엇인가요?