brunch

You can make anything
by writing

C.S.Lewis

by 이지원 Oct 01. 2022

단위 통합 E2E 테스트 프레임워크 개념


TMI

2000년대 초반 해외 글로벌 기업에서 `SDET`라는 직군이 활동할 무렵 국내에는 테스트 아웃소싱이라는 비즈니스 모델이 성공적으로 시장에 안착했었다. 독립적인 환경에서 품질 보증 활동을 진행하는 3자 테스팅, 나의 첫 커리어도 3자 테스팅 조직에서 시작했었다.


3자 테스팅의 장점은 확실하다. 쉽게 말해 신선한 시각으로 제품의 비즈니스 로직을 출시 전 블랙박스 형태로 검증하기 때문에 기능 이슈(UI 레벨)뿐 아니라 사용성과 같은 비기능적인 요구사항에서의 오류도 새로운 시각에서 발견할 수 있기 때문이다. 또한 인력 중심의 모바일 호환성 테스트의 강점도 분명 존재했기에 당시에는 국내 SW QA 시장을 장악할만한 비즈니스 모델이라 생각한다.


하지만 3자 테스팅 조직(인력 중심)에 속해 커리어를 쌓아가는 구성원들에게는 QA로서의 업무 환경과 처우 그리고 직업인으로서의 비전과 목표를 제시하지 못했다고 생각한다.(통합, 인수 테스트 레벨이 전문성이 낮다는 의미가 아닌, 인력 중심에서의 역량 강화만 진행하기 때문에)


첫 커리어를 아웃소싱에서 시작하다 보니, 익숙한 블랙박스 테스트에서 여러 갈래로 나눠지는 지식 학습에는 크게 거부감이 없었지만, `V 모델 관점에서 인수, 통합 이외의 로우 레벨` 환경에 대한 품질 보증 활동에는 굉장히 추상적이고 난해한 분야로만 다가왔었다. 아마도 201x 년대에 아웃소싱에서 첫 커리어를 시작한 QA라면 어떤 얘기인지 공감할 것이다. 특히 나처럼 비전공자에 테스터로 입사한 경우라면 더욱 그럴 것이라 생각된다.


이번 블로깅의 목표는 비전공자에 아웃소싱에서 `SW QA 커리어를 시작했고 통합, 인수 테스트 레벨에서만 품질 보증 활동을 해온 SW QA가 알고 있으면 좋을법한 개념`들을 예시를 통해 간단히 다뤄보고자 한다.


단위 테스트는 무엇인가?

매뉴얼 테스트가 완성된 비즈니스 로직(또는 테스트 필요한 시점에서의 로직)의 유효성 및 특정 조건을 사용자 레벨에서 보장하는지 검증하는 것이라면, 단위 테스트는 코드 레벨에서 비즈니스 로직이 특정 조건들의 만족 여부를 검증하는 것이라 할 수 있다. `즉 함수 또는 클래스 안의 메서드처럼 작은 단위의 로직들을 검증하기 위한 테스트이다.` 


단위 테스트를 위한 라이브러리

파이썬을 기준으로, unittest라는 파이썬 표준 라이브러리가 존재하고 pip를 통해 설치하는 pytest 라이브러리가 존재한다. 나 같은 경우 앞으로의 커리어를 Java를 기반으로 한 SDET가 목표인지라 Junit, TestNG와 같은 Java 테스트 프레임워크를 보다 학습할 예정이지만, 가장 최근 테스트 자동화 경험이 Python 환경이었기 때문에 Python 기준으로 기재하였다. 


경험상 UI 테스트 즉 SW QA 사이드에서 진행하는 자동화는 대표적으로 셀레니움과 앱피움과 같은 기술로 진행하므로 실제 사용자와 유사하게 UI 오류를 검출하는 방식이기 때문에 `테스트 시나리오에 의존성이 많았다.` 따라서 테스트 시나리오를 파라미터화 할 수 있는 `픽스처(fixture)`라는 객체가 필요하다. `E2E 테스트는 각 상황에서의 의존성이 많기 때문에 Pytest가 적합했다.`


하지만 단위 테스트는 `unittest에서 이미 다양한 헬퍼` 기능을 제공하고 있어서 `단위 테스트를 위해 Pytest가 필요한지는 모르겠다.` 


unittest

`unittest`는 표준 라이브러리에 포함되어 있기에 편리하게 사용할 수 있고 `풍부한 API`를 제공한다. unittest의 모듈들은 자바의 `Junit 기반이라 객체지향적`이다. 테스트는 객체를 사용해 작성되고 단위 테스트를 작성하려면 `unittest.TestCase`를 상속하여 테스트 클래스를 만들면 된다. 클래스 안의 메서드에는 테스트할 대상을 구현하면 된다. 메서드는 `test_` 로 시작해야 하며 `unittest.TestCase`에서 상속받은 `assertEqual`과 같은 메서드를 사용하여 조건의 참 거짓 여부를 검증한다.

테스트가 실패할 경우 콘솔 창에서 `AssertionError`에 해당하는 로그 확인이 가능하다.


pytest

`WebdriverIO(JS)`로 웹 모바일 테스트 코드를 구현하다 내부 사정으로 인해 Python 테스트 프레임워크 활용이 필요했던 시기가 있었고, 가장 처음 활용한 것이 `pytest`였다. 이후에는 `pytest`에서 bdd 프레임워크인 behave로의 전환이 있었다. `pytest-bdd`도 선택지가 있었지만 내부 사정으로 `behave`를 사용했었다.


내가 경험한 `pytest`와 `unittest`의 차이점은, 앞서 unittest 같은 경우 `unittest.TestCase`를 상속하기 위한 테스트 클래스를 작성해야 한다. 하지만 `pytest`에선 강제되지 않는다. 즉 단순히 테스트 필요한 함수를 만들고 `assert`를 통해 텍스트 또는 `request.status`와 같은 값들을 비교할 수 있는 것이다. 


이 점에 있어서 보다 자유롭게 테스트 코드를 작성할 수 있다는 장점이 존재했다. 


단점은 `unittest`와 비교했을 때 딱히 느끼지 못했었고 오히려 `pytest`에서 `unittest`의 역할도 가능하기 때문에 굳이 `unittest`를 사용할 필요성을 느끼지 못했었다.


pytest는 실제 `Appium` 예제를 통해 살펴보겠다. WebdriverIO에서 pytest로 전환하는 과정에서 공통 메서드를 설계하고, 테스트 클래스에서 상속받아 테스트 필요한 메서드를 구현한 예제이다. WebdriverIO에서 동작한 코드가 pytest에서 동작하는지 확인하기 위한 PoC 느낌의 코드이다. 당시 `BDD`를 활용해야 했기 때문에 실무 레벨에서 활용되지는 않았지만, BDD가 필요치 않았다면 이러한 구조로 웹 모바일 E2E 테스트 자동화를 설계하지 않았을까 생각된다.

당시 작업한 프레임워크 디자인은 아래이다. `로그인 시나리오를 선형 구조로 설계`한다면 `유지 보수`가 어려울뿐더러 테스트 시나리오 개수가 늘어날수록 `로케이터 관리 및 테스트 로직 관리`에 어려움이 많았다. 따라서 로그인에 필요한 동작들을 각 `스크린 및 페이지 단위로 구분하여 메서드를 설계`하고, 실제 테스트 로직에서 `적은 수의 코드를 가져다 쓰면 되는 구조`로 만들었다.

pytest의 가장 큰 장점

pytest의 가장 큰 장점은 `픽스처(Fixture)`이다. `픽스처`는 재사용 가능한 기능을 쉽게 만들어준다. 즉 `픽스처`를 통해 생성된 `데이터` 또는 `객체`를 재사용할 경우 유지보수 관점에서 `효율성`이 높아진다.


`테스트 스위트` 전반에 걸쳐 사용할 여러 객체를 생성하거나 데이터를 노출하는 장점 외에도 직접 호출되지 않는 함수를 수정 또는 사용될 객체를 미리 설정하는 등의 `사전 조건 설정`에도 사용될 수 있다.


픽스처를 정의하려면 우선 함수를 만들고 `@pytest.fixture` `데코레이터`를 작성하면 된다. 그리고 해당 픽스처를 활용하고자 하는 테스트에는, `파라미터로 픽스처의 네이밍`을 전달한다.


`pytest`의 픽스처를 활용할 경우 `DRY(Do not Repeat Yourself)`의 원칙을 준수할 수 있다는 장점이 있기에 `pytest`와 `selenium` 그리고 `appium`을 활용한 E2E 테스트 자동화 프레임워크를 디자인해야 한다면, 픽스처를 꼭 활용해보자.


마치며

지금까지 Python 환경에서의 단위 테스트 개념과 단위 통합 및 E2E 테스트 프레임워크에 대해 간단히 알아보았다. 


앞으로 새롭게 시작될 테스트 자동화 엔지니어 커리어에 있어서 어떤 언어로 설계하고 운영할지는 새로운 조직에 입사 후 내부 상황을 봐야겠지만, 개인적인 커리어 목표로는 테스트 자동화 엔지니어 커리어 패스를 밟아가면서 모바일 앱 개발이 가능한 수준의 개발 역량을 보유하는 것이라(실기기 자동화 이해도를 높이기 위해) 이왕이면 Python보단 Java 환경으로 새롭게 시작해보고 싶은 마음이 크다. 


아직 부족한 점이 많아 어떠한 기술 스택을 지녀야 할지, 내가 생각하고 있는 방향이 적절할지는 잘 모르겠지만 우선 생각하는 방향대로 시작해보려 한다.


다만 새롭게 E2E 환경을 구축하는 조직이라면 pytest에서 Selenium Appium을 활용하는 것도 초기 구축 비용뿐 아니라 Java에 비해 유지보수가 쉽기 때문에 Java 테스트 환경보단 Python을 추천하는 편이다. BDD 전환도 pytest-bdd와 behave라는 선택지가 있고, 내부 디바이스 팜 구축이 어렵다면 클라우드 테스트 서비스로 CICD 환경에서 호환성 및 기능 검증이 필요해지는 순간이 찾아올 텐데, python에서 제공하는 테스트 프레임워크와 클라우드 테스트 서비스의 호환 그리고 테스트 관리 툴과의 호환도 뛰어나므로, 특별한 이유가 아니라면 Java보단 Python을 추천하는 편이다. 


성능면에서도 큰 차이를 못 느꼈었고 Java로 구현한 자동화 로직은 Python으로도 동일하게 구현할 수 있기 때문에 비교적 접근이 쉬운 Python 환경에서 E2E를 구축하는 것도 좋은 방법이 될 것이라 생각한다.

매거진의 이전글 E2E 테스트 자동화 워크플로우 구축 PoC 경험담
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari