Clean ABAP ⑫ 테스트 설계: 원칙, 테스트 클래스, 의존성 주입
3줄 요약
테스트하기 좋은 구조를 먼저 만들고, 외부에 공개한 동작을 중심으로 검증해요.
테스트 클래스는 대상 코드 가까이에 두고, 외부 의존성은 생성자 등을 통해 전달해요.
테스트 더블은 실제 의존성을 대신하는 객체예요. TEST-SEAM은 기존 코드를 개선하기 위한 임시 수단으로 검토하세요.
어떤 상황에서 쓰나요
테스트를 작성하려 해도 DB나 다른 클래스에 의존하는 코드 때문에 막힐 수 있어요. 이번 글에서는 테스트하기 좋은 구조를 만들고, 실제 의존성을 테스트용 대체 객체로 바꾸는 방법을 알아봐요. 다음 글에서는 개별 테스트의 이름과 검증 방법을 다뤄요.
외부 구성 요소를 인터페이스로 분리하면 테스트에서 실제 DB 대신 테스트 더블을 연결할 수 있습니다. 아래 그림은 운영용 연결과 테스트용 연결을 구분해 보여 줍니다.
핵심 내용
원칙
자동으로 테스트할 수 있게 코드를 써요. 그러려면 리팩터링이 필요하면 새 기능보다 먼저 해요. 레거시에 코드를 더한다면 적어도 내가 더한 부분은 테스트할 수 있을 만큼 정리해요.
다른 코드에서 이 클래스를 사용할 때 테스트용 대체 객체로 바꿀 수 있게 설계해요. 바깥에 보이는 곳마다 인터페이스를 두고, 테스트 더블이나 설정 대체 수단을 제공해요.
테스트 코드는 운영 코드보다 더 읽기 쉽게 써요. 운영 코드가 복잡해도 읽기 좋은 테스트가 있으면 기대 동작을 확인할 수 있어요. 테스트 코드까지 이해하기 어렵다면 수정의 영향을 판단하기도 어려워져요.
$TMP에 오브젝트를 복사해 두고 만져 보거나, 손으로 반복 실행하는 테스트 리포트를 만들지 않아요. 그 리포트를 단언이 있는 유닛 테스트로 자동화하는 것이 다음 단계예요(원문의 "가난한 사람의 테스트").외부에 공개한 동작을 테스트하고, 비공개 구현에 직접 의존하는 테스트는 피하세요. private 메서드를 테스트하고 싶다는 충동은 설계 결함의 신호일 수 있어요. 클래스 안에 별개의 개념이 묻혀 있지 않은지, 업무 규칙과 프레임워크 연결 코드를 분리했는지(BOPF 액션이나 Gateway의
*_DPC_EXT에 로직을 직접 쓰는 경우), 인터페이스가 너무 복잡한지 물어보라고 해요.커버리지는 빠뜨린 테스트를 찾는 도구이지 KPI가 아니에요. 단언 없는 가짜 테스트로 숫자를 채우지 말아요.
테스트 클래스
로컬 테스트 클래스 이름은 "when"(
ltc_<공개 메서드 이름>)이나 "given"(ltc_<공통 준비 상태>)으로 지어요.ltc_test나 대상 클래스 이름 반복은 정보가 없어요.유닛 테스트는 대상 클래스의 로컬 테스트 인클루드에 두어 리팩터링하는 사람이 바로 찾고 한 번에 실행할 수 있게 해요. 컴포넌트, 통합, 시스템 테스트는 따로 전역 클래스의 로컬 테스트 인클루드에 두고, 그 전역 클래스를
FOR TESTING과ABSTRACT로 해서 운영 코드가 참조하지 못하게 해요."! @testing recruting같은 테스트 관계를 달면 해당 클래스에서 Shift+Ctrl+F12 (macOS는 Cmd+Shift+F12)로 테스트를 실행할 수 있어요.여러 테스트 클래스가 쓰는 도움 메서드는 상속이나 위임으로 도움 클래스에 모아요.
ADT 단축키: Ctrl+Shift+F9(전체 미리보기), F10(클래스의 테스트 실행), F11(커버리지 포함), F12(테스트 관계로 걸린 다른 클래스의 테스트까지). macOS는 Cmd 예요.
테스트 대상 코드(CUT)
변수 이름은
blog_post,empty_blog_post처럼 의미 있게 짓고, 마땅한 이름이 없으면cut(code under test)으로 두어도 돼요.clean_fra_blog_post처럼 클래스 이름을 되풀이하지 않아요.대상 변수의 타입은 클래스가 아니라 인터페이스로 해요.
호출에 필요한 파라미터가 많으면 기본값을 채워 주는 도움 메서드(
map_xml_to_itab)로 호출을 뽑아내요.
주입
의존성 역전을 적용할 때는 외부 구성 요소를 인터페이스로 분리하고, 생성자 등을 통해 전달해요. 세터 주입(
set_customizing_reader)은 운영 코드를 의도하지 않게 쓰이게 하고,FRIENDS주입은 운영용 의존성을 먼저 만들어 버리고 내부 이름이 바뀌면 깨지며 생성자 초기화를 건너뛰어서 피해요.테스트 더블은
cl_abap_testdouble부터 써 봐요. 직접 만든 테스트 클래스보다 짧고 이해하기 쉬워요. 사용 가능한 도구와 예제는SAP-samples/abap-test-isolation-examples저장소에 있어요.테스트 심(
TEST-SEAM)은 다른 방법이 다 안 될 때, 레거시를 리팩터링하기 위한 임시 우회책으로만 써요. 운영 코드에 테스트용 구간을 추가하고 내부 구현에 의존하므로 장기적으로 유지하기 어려워요.CREATE PRIVATE클래스의 의존성 역전 생성자는LOCAL FRIENDS로 접근해요. 단LOCAL FRIENDS로 private 멤버에 목 데이터를 심는 것은 내부 구조가 바뀌면 깨지므로 하지 않아요.운영 코드에
IF is_unit_test_running = abap_true.같은 테스트 전용 기능을 넣지 않아요. 시뮬레이션 전기 같은 사용자용 테스트 기능은 도메인의 일부라 괜찮아요.목을 만들려고 서브클래스를 만들어 메서드를 재정의하지 않아요. 깨지기 쉽고 실제 소비자가 상속할 길도 열어 버려요. 대신 다른 테스트 도구를 쓰거나 문제 메서드를 인터페이스 있는 별도 클래스로 빼요.
필요 없는 것은 목으로 만들지 않고, 필요 없는 데이터도 채우지 않아요. 부작용 없는 데이터 컨테이너는 목 없이 운영용을 그대로 써도 돼요.
테스트 케이스 ID로 데이터를 고르는 테스트 프레임워크를 만들지 않아요. 유닛 테스트는 데이터를 넣으면 데이터가 나오는 구조로 필요한 데이터를 그 자리에서 정의해요.
주의할 점
가이드는
cl_abap_testdouble, ABAP Unit이 있는 릴리스를 전제로 해요. 어느 릴리스부터 쓸 수 있는지는 원문에 적혀 있지 않아서 쓰기 전에 대상 시스템에서 확인하세요.테스트 심과 서브클래스 목에 대한 의견은 레거시 현실과 충돌할 수 있어요. 가이드는 "서브클래스 목은 깨지기 쉽고, 테스트 심은 같이 깨지기 쉽지만 운영 동작은 안 바꾸므로 더 깨끗하다"는 순서로 말해요.
원문은 2019년 첫 공개, 2025년 3월 마지막 수정본이에요. 이 글은 읽고 정리한 것이고 예제를 직접 돌려 보지는 않았어요.
원문 주소: https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#testing
출처와 이용 안내
원문: Clean ABAP - Testing: Principles, Test Classes, Code Under Test, Injection · 작성자 SAP SE and contributors SAP/styleguides · 작성일 2019-05-01 · 기준 릴리스 무관 ABAP Unit, cl_abap_testdouble 사용 가능한 릴리스 · 확인일 2026-10-25
이 글은 위 원문을 읽고 한국어로 요약·재구성한 글이며 번역본이 아니에요. 원문의 저작권은 작성자와 SAP에 있어요.
원문은 CC BY 3.0 라이선스(https://creativecommons.org/licenses/by/3.0/)로 공개된 자료예요. 이 글은 내용을 한국어로 줄이고 순서를 바꾼 변경본이며, 원저작자가 이 글을 보증하지 않아요.
설정과 화면은 릴리스마다 달라요. 적용하기 전에 원문과 SAP Help Portal, 관련 SAP Note에서 최신 내용을 확인해 주세요.
SAP와 SAP 제품명은 SAP SE의 상표예요. 바로투입은 SAP와 관련이 없어요.
댓글 0
아직 댓글이 없어요.
로그인하고 댓글 쓰기