상태 전이 테스트란?상태 전이도·전이표의 작성법과 실례를 알기 쉽게 해설【Playwright 대응】

테스트 자동화

상태 전이 테스트란 시스템이 가진 「상태」와 「상태를 변화시키는 이벤트」를 정리하여 전이가 올바르게 동작하는지를 검증하는 테스트 설계 기법입니다. 로그인 플로우·EC 카트·예약 시스템 등 상태를 가진 시스템의 테스트에서 특히 효과를 발휘합니다.

상태 전이 테스트를 사용하면 「정상적인 전이가 올바르게 동작하는가」뿐만 아니라 「있어서는 안 되는 전이가 올바르게 거부되는가」까지 체계적으로 테스트할 수 있어 플로우 계열 버그를 근본적으로 방지할 수 있습니다.

📌 이런 분께 추천합니다

  • 상태 전이 테스트를 처음 배우는 QA 엔지니어·개발자
  • 로그인·카트·주문 플로우 테스트를 체계화하고 싶은 분
  • Playwright E2E 테스트의 시나리오 설계에 활용하고 싶은 분
  • ISTQB에서 상태 전이 테스트를 이해하고 싶은 분

✅ 이 글을 읽으면 얻을 수 있는 것

  • 상태 전이 테스트의 개념·상태 전이도·상태 전이표의 작성법을 알 수 있다
  • 로그인 플로우·EC 카트에의 구체적인 적용 방법을 알 수 있다
  • Playwright × pytest로의 E2E 테스트 응용 방법을 알 수 있다

👤 이 글을 쓴 사람

QA 엔지니어·테스트 자동화 엔지니어로서 15년 이상의 실무 경험을 가진 Yoshi가 집필. 상태 전이 테스트는 EC 사이트·예약 시스템·인증 플로우 등 상태를 가진 시스템에서 매일 활용하는 기법입니다. 구현 코드는 GitHub에 공개 중입니다: github.com/YOSHITSUGU728/automated-testing-portfolio

「로그아웃 상태에서 주문 확정 버튼을 누르면 어떻게 될까?」「취소 완료된 주문을 다시 취소할 수 있어버린다?」——이런 「있어서는 안 되는 조작」의 테스트를 놓치고 있지 않으신가요?

  • 정상 플로우만 테스트하여 비정상적인 상태 전이가 누락된다
  • 어떤 상태에서 어떤 조작이 가능한지가 정리되지 않는다
  • 플로우가 복잡해질수록 테스트 케이스가 발산해버린다

상태 전이 테스트는 이런 문제를 해결하는 기법입니다. 이 글에서는 개념·상태 전이도·상태 전이표의 작성법부터 Playwright E2E 테스트로의 응용까지 한 번에 해설합니다.

📌 결론

  • 상태·이벤트·전이 대상·액션을 정리한 테스트 설계 기법으로 정상 전이와 무효 전이 양쪽을 테스트한다
  • 상태 전이도로 전체상을 시각화하고 상태 전이표로 테스트 케이스를 망라적으로 도출한다
  • Playwright E2E 테스트와 궁합이 최상으로 각 상태를 fixture·각 전이를 테스트 함수로 구현할 수 있다

상태 전이 테스트란?

상태 전이 테스트란 「시스템이 가진 상태」「상태를 변화시키는 이벤트(조작)」「전이 후 상태」「실행되는 액션」을 정리하여 모든 전이가 올바르게 동작하는지를 검증하는 테스트 설계 기법입니다.

예를 들어 EC 사이트의 주문 플로우에서는 「카트 미추가」→「카트 추가 완료」→「주문 확정」→「발송 완료」→「수령 완료」라는 상태 변화가 발생합니다. 상태 전이 테스트는 이 흐름을 도표나 표로 정리하여 모든 패턴을 빠짐없이 테스트합니다.

비교 항목상태 전이 테스트 없음상태 전이 테스트 있음
테스트 범위정상 플로우만 되기 쉽다정상·이상 전이를 망라
무효 조작 검증누락이 많다표로 체계적으로 확인 가능
팀 공유구두·문서로 설명 필요도표·표로 직관적으로 공유
E2E 테스트로의 변환시나리오가 즉흥적이 된다전이마다 테스트 함수를 설계

상태 전이 테스트의 기본 요소란?

상태 전이 테스트를 설계하려면 다음 4가지 요소를 정리합니다.

요소설명예시
상태(State)시스템이 현재 어떤 상태에 있는가로그아웃 중·로그인 중·주문 확정
이벤트(Event)상태를 변화시키는 조작·입력로그인 버튼 클릭·주문 확정 버튼
전이(Transition)상태에서 이벤트로 인해 다음 상태로 변하는 것로그아웃 중 → 로그인 중
액션(Action)전이 시에 실행되는 처리세션 발행·확인 메일 발송
💡 포인트:상태 전이 테스트에서는 「정상적인 전이」뿐만 아니라 「무효 전이(그 이벤트가 발생해도 상태가 변하지 않아야 하는 케이스)」도 테스트하는 것이 중요합니다. 무효 전이의 누락이 실무에서 가장 많은 버그의 온상이 됩니다.

상태 전이도(State Diagram)의 작성법이란?

상태 전이도는 상태를 원(○)·전이를 화살표(→)·이벤트를 라벨로 나타낸 도표입니다. 전체 흐름을 직관적으로 파악할 수 있습니다.

※ 상태는 「원」、전이는 「화살표」、이벤트는 「라벨」로 표현합니다. 도표를 처음 읽는 경우에는 먼저 원(상태)을 확인하고 화살표(전이)를 따라가 보세요.

📊 로그인 플로우의 상태 전이도

로그아웃 중
로그인 성공
로그인 중
주문 확정
주문 확정

로그아웃
(자기 자신으로)

로그아웃
(로그아웃 중으로)

취소 신청
(취소 완료로)

※ 원=상태 화살표=전이 라벨=이벤트

상태 전이도의 장점

  • 전체 흐름을 한눈에 파악할 수 있다:상태와 전이의 관계가 시각적으로 이해된다
  • 팀 설명이 쉬워진다:개발·QA·비즈니스 측이 공통 인식을 가질 수 있다
  • 누락 발견에 도움이 된다:도표를 그리는 과정에서 「이 상태로의 전이가 없네?」라는 깨달음이 생긴다

상태 전이표(State Transition Table)의 작성법이란?

상태 전이표는 상태 전이도를 표 형식으로 변환한 것입니다. 각 상태×각 이벤트의 조합으로 「전이 대상」 또는 「무효(—)」를 기입함으로써 테스트 케이스를 망라적으로 도출할 수 있습니다.

실례:로그인 플로우의 상태 전이표

현재 상태로그인 성공로그인 실패로그아웃주문 확정취소
로그아웃 중로그인 중로그아웃 중
(에러 표시)
로그인 중로그아웃 중주문 확정
주문 확정취소 완료
취소 완료
(무효·에러)

표 중의 「—」는 그 이벤트가 현재 상태에서는 무효(발생해서는 안 되거나 발생해도 상태가 변하지 않는)임을 나타냅니다. 이 「—」 부분이 바로 「무효 전이 테스트」의 테스트 케이스가 됩니다.

💡 중요:표 중의 「—(무효 전이)」는 모두 테스트 대상입니다.

무효 전이 테스트를 생략하면 「취소 완료된 주문을 다시 취소할 수 있어버린다」「로그아웃 상태에서 API를 직접 호출하면 주문이 통과되어버렸다」라는 버그를 놓칩니다. 정상 전이뿐만 아니라 「—」셀을 반드시 테스트하는 습관을 기르세요.

실례:EC 사이트 주문 플로우

더 실무에 가까운 예로서 EC 사이트의 주문 플로우를 테스트 케이스에 반영해 봅니다.

테스트 케이스현재 상태이벤트기대되는 전이 대상확인 포인트
TC-01 ✅카트 미추가상품 추가카트 추가 완료카트 배지 수가 늘어나는가
TC-02 ✅카트 추가 완료구매 확정주문 확정확인 메일이 발송되는가
TC-03 ✅주문 확정취소 신청취소 완료재고가 복구되는가·환불 처리가 실행되는가
TC-04 ❌카트 미추가구매 확정(무효)카트 미추가(변화 없음)에러 또는 버튼이 비활성화되어 있는가
TC-05 ❌취소 완료재취소(무효)취소 완료(변화 없음)에러 또는 조작할 수 없는 상태인가
TC-06 ❌발송 완료취소 신청(무효)발송 완료(변화 없음)취소 버튼이 비표시인가·에러인가

✅는 정상 전이 테스트(올바른 조작이 올바르게 동작한다),❌는 무효 전이 테스트(무효 조작이 올바르게 거부된다)를 나타냅니다. 양쪽을 커버함으로써 플로우 전체의 품질을 담보할 수 있습니다.

Playwright × pytest에의 응용

상태 전이 테스트는 Playwright × pytest의 E2E 테스트와 매우 궁합이 좋습니다. 「각 상태를 fixture·각 전이를 테스트 함수」로 구현하는 것이 실무의 베스트 프랙티스입니다.

폴더 구성 예시

tests/
├── conftest.py              # fixture 정의(상태 준비)
└── e2e/
    └── test_order_flow.py   # 주문 플로우의 상태 전이 테스트

conftest.py:상태를 fixture로 준비한다

import pytest
from playwright.sync_api import Page

@pytest.fixture
def logged_in_page(page: Page):
    """상태:로그인 중(로그인 완료 페이지를 반환)"""
    page.goto("localhost:3000/login")
    page.fill("#username", "test_user")
    page.fill("#password", "secret_pass")
    page.click("#login-btn")
    page.wait_for_url("**/dashboard")
    return page

@pytest.fixture
def cart_added_page(logged_in_page: Page):
    """상태:카트 추가 완료(로그인 완료+상품 추가 완료)"""
    logged_in_page.goto("localhost:3000/products/1")
    logged_in_page.click("#add-to-cart")
    logged_in_page.wait_for_selector(".cart-badge")
    return logged_in_page

test_order_flow.py:전이를 테스트 함수로 구현한다

from playwright.sync_api import Page, expect

# TC-01:카트 미추가 → 상품 추가 → 카트 추가 완료
def test_add_item_to_cart(logged_in_page: Page):
    logged_in_page.goto("localhost:3000/products/1")
    logged_in_page.click("#add-to-cart")
    expect(logged_in_page.locator(".cart-badge")).to_have_text("1")

# TC-02:카트 추가 완료 → 구매 확정 → 주문 확정
def test_confirm_order(cart_added_page: Page):
    cart_added_page.goto("localhost:3000/cart")
    cart_added_page.click("#checkout-btn")
    expect(cart_added_page.locator(".order-status")).to_have_text("주문 확정")

# TC-04:카트 미추가 → 구매 확정(무효 전이)
def test_checkout_without_cart(logged_in_page: Page):
    logged_in_page.goto("localhost:3000/cart")
    # 카트가 비어 있을 때는 구매 버튼이 비활성화되어 있는지 확인
    expect(logged_in_page.locator("#checkout-btn")).to_be_disabled()

# TC-05:취소 완료 → 재취소(무효 전이)
def test_cancel_already_cancelled_order(logged_in_page: Page):
    logged_in_page.goto("localhost:3000/orders/cancelled-order")
    # 취소 완료 주문에는 취소 버튼이 존재하지 않는 것을 확인
    expect(logged_in_page.locator("#cancel-btn")).not_to_be_visible()
💡 실무 팁:fixture로 「상태를 만드는」 것과 테스트 함수로 「전이를 검증하는」 것을 분리하는 것이 포인트입니다. 이렇게 하면 「로그인 중」이라는 상태를 여러 테스트에서 재사용할 수 있어 테스트 코드의 중복이 없어지고 유지보수성이 높아집니다.

⚠️ 상태 전이 테스트에서 자주 있는 실패 패턴 4선

실무에서 상태 전이 테스트를 설계할 때 빠지기 쉬운 실패를 소개합니다.

① 정상 전이만 테스트하여 무효 전이를 놓친다

「정상적인 플로우로 올바르게 동작하는 것」의 테스트만으로 만족해버리는 것이 가장 흔한 실패입니다. 「취소 완료된 주문을 다시 취소할 수 있어버린다」「로그아웃 상태에서 API를 직접 호출하면 주문이 통과되어버렸다」라는 버그는 모두 무효 전이의 누락입니다. 상태 전이표의 「—」셀을 반드시 테스트하는 습관을 기르세요.

② 상태의 정의가 모호한 채로 테스트를 시작한다

「로그인 중」과 「세션 기한 만료」는 다른 상태입니다. 「주문 확정」과 「결제 완료」도 다른 경우가 있습니다. 상태의 경계가 모호한 채로 테스트를 시작하면 커버되지 않은 상태가 생깁니다. 사양서를 확인하면서 상태를 명확하게 정의하고 나서 설계를 시작하세요.

③ 상태 전이도만 만들고 상태 전이표를 생략한다

상태 전이도는 「전체 흐름」을 파악하는 데 편리하지만 그것만으로는 테스트 케이스의 망라성을 담보할 수 없습니다. 상태 전이표에 반영함으로써 「이 상태×이 이벤트의 조합을 테스트했는가」가 한눈에 알 수 있게 됩니다. 도표와 표 양쪽을 만드는 것이 프로의 설계입니다.

④ E2E 테스트에서 상태 준비를 테스트 함수 안에 써버린다

「로그인→상품 추가→구매 확정→취소」의 일련의 조작을 모두 1개의 테스트 함수에 써버리는 케이스입니다. 이렇게 하면 앞의 전이가 실패하면 뒤의 테스트를 실행할 수 없게 됩니다. pytest의 fixture로 「상태를 준비하는 처리」를 분리함으로써 각 테스트가 독립적으로 실행될 수 있게 됩니다.

FAQ

Q. 상태 전이 테스트는 어떤 시스템에 사용해야 하나요?

「상태」를 가진 시스템 전반에 유효합니다. EC 사이트(카트·주문·결제·배송)·예약 시스템(가예약·확정·취소)·인증 플로우(로그아웃·로그인·세션 기한 만료)등이 대표적인 예입니다. 반대로 상태를 가지지 않는 단순한 입력 폼이나 계산 처리에는 동등 분할이나 경계값 분석이 더 적합합니다.

Q. 상태 전이 테스트와 유스케이스 테스트의 차이는?

상태 전이 테스트는 「상태와 그 전이가 올바른가」에 주목합니다. 무효 전이 테스트도 포함합니다. 유스케이스 테스트는 「사용자의 목표로의 일련의 조작 플로우」를 테스트합니다. 실무에서는 양쪽을 조합하는 경우가 많아 유스케이스 테스트로 정상 플로우를 검증하면서 상태 전이 테스트로 무효 전이를 보완하는 구성이 일반적입니다.

Q. ISTQB에서 상태 전이 테스트는 어느 정도 이해하면 합격할 수 있나요?

ISTQB Foundation Level에서는 「상태 전이도·상태 전이표의 읽는 방법과 기본적인 테스트 케이스 도출법」이 출제됩니다. 이 글의 로그인 플로우 예시(상태 전이도·상태 전이표·정상 전이와 무효 전이의 구별)레벨이 이해되어 있으면 합격 라인입니다. 「0스위치 커버리지(전체 상태)」「1스위치 커버리지(전체 전이)」의 용어도 파악해 두세요.

Q. 상태가 너무 많아진 경우에는 어떻게 하면 되나요?

상태가 10개를 넘으면 상태 전이표가 너무 거대해집니다. 그 경우에는 「서브시스템 단위로 테이블을 분할한다」「우선도가 높은 전이(빈도가 높다·리스크가 높다)부터 먼저 테스트한다」는 방법이 유효합니다. 전체 패턴을 커버하는 것보다 리스크 베이스로 중요한 전이에 집중하는 판단도 실무에서는 중요합니다.

실무에서는 상태 전이도를 draw.io 등의 도구나 스프레드시트로 작성하고 리뷰 후에 Playwright × pytest의 E2E 테스트에 반영하는 워크플로우가 자주 사용됩니다. fixture로 「상태」를 테스트 함수로 「전이」를 표현함으로써 설계서와 코드가 1대1로 대응하는 유지보수성이 높은 테스트 스위트가 완성됩니다.

📋 이 글의 정리

  • 상태 전이 테스트는 「정상 전이」와 「무효 전이」 양쪽을 테스트하는 테스트 설계 기법
  • 상태 전이도로 전체 흐름을 시각화하고 상태 전이표로 테스트 케이스를 망라적으로 도출한다
  • 표 중의 「—」(무효 전이)야말로 버그의 온상. 반드시 테스트한다
  • Playwright × pytest에서는 fixture로 상태를·테스트 함수로 전이를 각각 구현하는 것이 베스트 프랙티스
  • 상태가 너무 많은 경우에는 서브시스템 분할·리스크 베이스 테스트로 우선순위를 정한다

상태 전이 테스트의 최대 가치는 「정상 플로우만으로는 알 수 없는 버그」를 체계적으로 발견할 수 있는 점입니다. 먼저 로그인 플로우나 주문 플로우 등 가까운 시스템의 상태 전이도를 1장 그려보는 것부터 시작하세요. 도표를 그리는 것만으로 「이 전이 테스트, 하지 않았었다!」라는 깨달음이 반드시 생깁니다.

제목과 URL을 복사했습니다