Zephyr v3.7.0 · 테스트 실행 경로

Zephyr Twister: 무엇을 골라서, 어디까지 검증했나

Twister의 결과 한 줄에는 시나리오 선택, 보드 적합성, 빌드, 실행 환경, 판정 방식이 겹쳐 있습니다. 이 경계를 분리해야 “빌드됨”을 “동작이 증명됨”으로 읽지 않습니다.

이 글의 기준은 Zephyr v3.7.0과 해당 소스 commit 36940db938a8f4a1e919496793ed439850a221c2이다. 명령·YAML·그림은 선택 원리를 설명하며 특정 호스트나 보드에서 실행했다는 기록은 아니다. 실제 결과는 도구 설치, 플랫폼 메타데이터와 연결된 장치에 따라 달라진다.

1. 하나의 앱 빌드에서 테스트 행렬로

Build System / west의 west build는 지정한 앱과 보드의 빌드를 따라간다. Twister는 저장소의 testcase.yaml과 sample.yaml을 찾아 각 시나리오를 플랫폼과 짝짓고, 조건에 맞는 조합을 빌드한다. 실행 가능한 환경에서는 바이너리를 돌리고 로그를 판정한다. 기본 실행은 보드 메타데이터의 testing.default: true 대상 위주이며 전체 보드·전체 테스트의 보증이 아니다.

그림 1. Twister가 만드는 결과는 다섯 관문을 지난다
① 발견testcase.yaml 또는 sample.yaml의 시나리오
② 조합선택한 플랫폼과 시나리오로 테스트 인스턴스 구성
③ 걸러냄태그, 지원 기능, 보드 자원, Kconfig 조건을 평가
④ 빌드남은 인스턴스를 보드별로 구성·컴파일
⑤ 실행·판정가능한 대상만 실행하고 harness·로그로 결과 수집

한 관문에서 제외된 조합은 뒤 관문의 실행 성공·실패와 같은 뜻이 아니다.

근거: 3.7.0 Twister: 기본 대상·build only·탐색, 고정 소스 TestPlan.

2. YAML의 한 항목이 하나의 시험 조건을 만든다

프로젝트 디렉터리의 tests: 아래 항목이 시나리오다. Zephyr 3.7.0 samples/hello_world/sample.yaml에는 sample.basic.helloworld가 있고, common의 harness: console 및 출력 정규식이 이 시나리오에 적용된다. 이것은 소스 코드 안의 Ztest assertion 자체가 아니다. Twister가 어느 앱을, 어느 조건으로, 어떻게 판정할지 알려 주는 메타데이터다.

표 1. hello_world 샘플에서 읽는 세 층
위치고정 소스의 값Twister에서의 역할
testssample.basic.helloworld선택과 결과에 쓰는 시나리오 ID
commontags: introduction, integration_platforms: native_sim태그와 integration 모드에서의 플랫폼 범위
commonharness: console + Hello World! 정규식실행 출력에서 판정할 패턴

시나리오 전체 식별자는 기본 상세 ID 기준으로 samples/hello_world/sample.basic.helloworld처럼 경로와 ID를 합친다. -T는 탐색할 루트 디렉터리를 추가하고, -s는 이 상세 시나리오를 지정한다. -T를 적었다고 그 아래의 모든 조합이 실행된다는 뜻은 아니다.

근거: 고정 hello_world/sample.yaml, 3.7.0 Tests 문서, 고정 CLI -T 정의, 고정 CLI -s 정의.

3. “선택했다”와 “이 보드에 적합하다”를 나눠 보기

-p/--platform은 시험할 플랫폼을 좁힌다. 생략하면 보드 메타데이터에서 기본 플랫폼을 고른다. -t/--tag는 시나리오 태그를 거른다. 그러나 명령행 선택을 통과해도 YAML의 platform_allow, depends_on, min_ram, filter 등에 맞지 않으면 그 시나리오·플랫폼 조합은 제외된다. 일부 filter 식은 Kconfig나 devicetree 값 확인을 위해 CMake 구성이 필요하다.

그림 2. 같은 시나리오도 플랫폼마다 다른 문턱을 지난다

각 칸의 통과는 예시 조건을 충족했다는 뜻이며 최종 빌드·실행 성공을 보장하지 않는다.

조합 단계
플랫폼 A
플랫폼 B
플랫폼 C
명령행 -p
선택됨
선택됨
선택되지 않음 → 종료
YAML depends_on
필요 기능 있음
필요 기능 없음 → 제외
평가 대상 아님
Kconfig filter
구성 결과로 평가 → 통과하면 빌드
앞 단계에서 제외
평가 대상 아님

이것은 필터 순서를 이해하기 위한 가상 플랫폼 A·B·C 예시다. 실제 우선순위와 제외 사유는 선택한 보드, 시나리오, Twister 옵션의 조합에서 확인한다.

표 2. 범위를 좁히는 곳마다 묻는 질문
조건위치질문
-T / -s명령행어떤 테스트 디렉터리 또는 시나리오를 후보로 만들까?
-p / 기본 플랫폼명령행·보드 메타데이터어느 플랫폼과 짝지을까?
-t / tags명령행·시나리오 YAML선택한 기능 분야에 속하는가?
depends_on / min_ram시나리오·보드 메타데이터필요 기능과 RAM 조건을 갖추었는가?
filter시나리오 YAML·구성 결과ARCH, PLATFORM, Kconfig 등 실제 식을 만족하는가?

근거: 3.7.0 보드 메타데이터, 3.7.0 YAML 필드와 filter, 고정 CLI -p 및 -t.

4. 빌드 통과가 곧 실행 통과는 아니다

선택된 인스턴스는 먼저 빌드된다. build_only: true는 실행 기능을 검증하지 않고 빌드 가능 여부만 확인한다. 그렇지 않아도 에뮬레이터가 없거나, 실기기 연결과 --device-testing 구성이 없거나, 필요한 harness·fixture를 준비하지 못하면 실행 단계에 도달하지 못할 수 있다. Twister의 -v 출력은 각 앱을 실제 실행했는지, 빌드만 했는지 보는 첫 단서다.

그림 3. 빌드 다음의 세 결과를 같은 PASS로 합치지 말자
빌드 전용시나리오 선택·빌드↓build_only: true 또는 --build-only↓컴파일 결과만 보고
에뮬레이터·native_sim시나리오 선택·빌드↓실행 가능한 시뮬레이션 환경↓출력과 harness 판정
연결된 실기기시나리오 선택·빌드↓--device-testing + serial/하드웨어 맵·runner↓플래시·출력·harness 판정

가운데·오른쪽 경로도 실행 환경과 개별 시나리오 조건이 맞을 때만 성립한다. 그림은 모든 시험이 세 갈래 중 하나로 성공한다는 약속이 아니다.

표 3. 통과한 단계에 따라 말할 수 있는 것
결과·옵션확인한 것여전히 미확인인 것
build_only: true / --build-only해당 설정으로 구성·컴파일 가능보드에서 동작하는지, 출력이 맞는지
시뮬레이터 실행 + harness 통과그 시뮬레이션 조건에서 기대한 실행 판정다른 보드의 전기적·시간 특성
--device-testing + 장치 실행 통과선택 장치·연결·fixture에서 기대한 실행 판정선택하지 않은 하드웨어·설정
필터로 제외그 조합은 이번 범위에 포함되지 않음성공·실패 어느 쪽도 결론 낼 수 없음

근거: 3.7.0 build-only·실행 조건, 3.7.0 실기기 실행, 고정 CLI --build-only 정의, 고정 CLI --device-testing 정의.

5. 먼저 작은 범위로 확인하기

Zephyr 환경과 빌드 도구가 준비되어 있다는 전제에서, 다음은 고정 소스에 있는 Hello World 샘플 하나를 플랫폼 하나로 좁히는 예시다. native_sim 지원 및 호스트 실행 가능 여부는 실제 설치 상태에 달려 있다. 각 명령은 별도 실행 예시이며, 바로 아래 결과가 실제로 관측됐다는 뜻은 아니다.

./scripts/twister -T samples/hello_world -p native_sim -v

--integration을 추가하면 이 샘플 YAML의 integration_platforms: native_sim처럼 지정한 integration 범위가 작동한다. 특정 ID만 다시 고를 때에는 -s samples/hello_world/sample.basic.helloworld를 쓴다. --all은 모든 플랫폼으로 범위를 키우므로 첫 재현 명령으로 쓰기보다 선택 목적을 정한 뒤 사용한다.

표 4. 옵션을 바꾸면 달라지는 축
선택바뀌는 범위주의
-T samples/hello_world탐색할 디렉터리결과 플랫폼은 따로 정해짐
-s samples/hello_world/sample.basic.helloworld상세 시나리오 ID플랫폼 적합성 필터를 우회하지 않음
-p native_sim한 플랫폼으로 한정실행 가능 여부는 호스트·시나리오 조건에 달림
--integrationintegration 플랫폼 지정 조건 활용기본 실행과 선택 집합이 달라질 수 있음
--build-only실행 단계를 생략런타임 판정으로 읽으면 안 됨
--device-testing연결된 장치에서 실행 요청serial 또는 hardware map 등 대상 설정 필요

근거: 3.7.0 integration 모드, 고정 CLI -T 정의, 고정 CLI -s 정의, 플랫폼 옵션.

6. 통과 숫자보다 먼저 제외 이유를 읽는다

기본 출력 폴더는 현재 작업 디렉터리의 twister-out이고, -O로 바꿀 수 있다. Twister의 JSON/JUnit 결과에는 시나리오·플랫폼·상태가 기록된다. 고정 버전에서는 --report-filtered를 켜면 제외된 조합도 twister.json에 포함되며, status: "filtered"와 reason으로 제외 사유를 확인할 수 있다. 같은 옵션 없이 보고서의 통과 개수만 비교하면 분모가 달라질 수 있다.

표 5. 어느 증거를 볼까
질문확인할 자료읽을 때의 경계
어떤 조합이 실제 후보였나?verbose 출력, twister.json시나리오 ID와 플랫폼을 함께 확인
왜 이 보드는 빠졌나?--report-filtered로 포함한 JSON의 status·reason제외는 실행 실패가 아님
빌드만 했나, 실행했나?-v 출력, 결과의 runnable·case 상태build-only 성공을 런타임 PASS로 확대하지 않음
테스트가 왜 실패했나?해당 인스턴스 빌드·실행 로그, twister.json구성 오류와 harness 판정 실패를 구별
CI에 전달할 결과가 필요한가?twister.xml JUnit, twister.jsonreport-dir·report-name 옵션을 사용했다면 위치/이름 확인
출력 폴더 주의: 일반 재실행에서 기존 출력 폴더가 있으면 기본적으로 twister-out.1처럼 이름을 바꾸어 보존한다. --clobber-output은 기존 폴더를 삭제하는 옵션이고, --no-clean은 재사용하는 옵션이다. --only-failed·--test-only 등도 기존 결과를 유지하는 별도 경로를 탄다. 필요한 결과를 보존하고, 비교할 때는 폴더와 실행 옵션을 함께 기록한다.

근거: 고정 CLI 출력·보고서 옵션, JSON 필터 포함 조건과 제외 사유, 기존 출력 폴더 보존·재사용·삭제 분기.

7. 결과가 예상과 다를 때의 확인 순서

  1. -T나 -s의 경로·ID가 YAML에 실제로 있는지 확인한다. sample.basic.helloworld와 sample.basic.hello_world는 다른 문자열이다.
  2. 보드의 testing.default와 명령행 -p, 시나리오의 integration_platforms를 함께 읽는다. 명시적으로 고르지 않은 플랫폼의 미실행은 실패 증거가 아니다.
  3. 태그, depends_on, 메모리 조건, filter, 느린 테스트·quarantine을 확인한다. -v와 제외 리포트에서 첫 제외 이유를 찾는다.
  4. 빌드 전용 설정인지, 런타임 환경과 harness가 준비됐는지 본다. 실기기 시험이라면 serial·runner·fixture와 --device-testing 설정을 기록한다.
  5. 실패를 재현할 때는 Zephyr commit, 보드 revision, toolchain, Twister 명령, 출력 폴더와 해당 인스턴스 로그를 같이 남긴다.

8. 고정 버전에서 확인한 근거

이 글은 Twister가 시험 대상을 편성하고 실행 결과를 수집하는 층을 다룬다. C 코드 안의 Ztest 스위트·fixture·assertion 작성법은 별도 주제다. 실기기·시뮬레이터를 돌린 성능이나 통과율을 제시하지 않는다.

연결해서 읽기