dev.to

I Let AI Write My Tests for 6 Months. Here Is What Actually Survived Production

6개월 동안 AI에게 테스트를 작성하게 해봤습니다 — 실제 프로덕션에서 살아남은 것들

AI는 테스트 코드의 보일러플레이트와 버그 재현용 골격을 빠르게 만드는 데 효과적이지만, 중요한 실패 시나리오와 올바른 검증 조건까지 찾아주지는 못합니다. 작성자는 Playwright와 Flutter 테스트 경험을 바탕으로 AI 생성 테스트의 한계와 사람이 반드시 맡아야 할 역할을 설명합니다.

AI 요약

작성자는 3년 넘게 테스트 자동화를 해왔으며, 웹에서는 Playwright(Playwright), 모바일에서는 Flutter를 주로 사용하고 있습니다. 최근 6개월 동안 테스트 작성 과정에 AI를 적극적으로 활용한 뒤, 실제로 생산성을 높인 부분과 겉보기만 그럴듯한 결과를 구분해 정리합니다. 계기는 동료가 PR 채널에 AI가 4초 만에 생성했다는 Playwright 테스트를 올린 일이었습니다. 테스트는 통과했지만 버튼을 클릭하고 3초를 기다린 뒤 페이지가 여전히 존재하는지만 확인하고 있었습니다. 초록색 성공 표시가 나왔지만 실제로 검증한 가치는 없었습니다.

■ 가장 효과가 컸던 활용: 버그 리포트를 테스트로 바꾸기

작성자가 꼽은 가장 큰 성과는 버그 리포트를 테스트 케이스의 초안으로 바꾸는 작업입니다. 예를 들어 QA 팀이 “쿠폰이 적용된 상태에서 마지막 상품을 삭제하면 장바구니 총액이 갱신되지 않습니다”처럼 자연어로 버그를 설명하면, 작성자는 해당 내용과 기존 page object 파일을 AI에 함께 제공합니다. 그러면 1분도 되지 않아 합리적인 실패 테스트를 얻을 수 있습니다. 완성된 테스트는 아니므로 assertion은 직접 다시 작성해야 하지만, import, fixture 설정, 페이지 이동 같은 지루한 보일러플레이트는 대부분 자동으로 처리됩니다. 작성자는 이 방식으로 타이핑 분량의 약 60%가 줄었다고 설명합니다.

■ 오래된 flaky 테스트를 분석하는 보조 도구

20번 실행할 때 한 번 정도만 실패하는 테스트, 특히 14개월 전에 퇴사한 사람이 작성했고 중첩된 대기 네 개와 8000ms 하드코딩 타임아웃이 들어 있는 테스트를 분석할 때도 AI가 도움이 됩니다. 테스트 코드와 trace를 함께 넣고 가능한 race condition을 물으면 AI가 절반 정도는 맞는 답을 제시합니다. 답이 틀리더라도 검증하거나 반박할 수 있는 가설을 제공하기 때문에, 파일을 아무 방향 없이 들여다보는 것보다는 빠르다고 합니다. 다만 AI의 설명을 원인으로 확정하는 것이 아니라, 사람이 실제 실패 조건을 확인하기 위한 출발점으로 사용해야 합니다.

■ 복잡한 DOM에서 locator 후보 찾기

HTML 일부를 제공하고 가장 안정적인 locator를 요청하면 AI는 작성자가 곧 만들 뻔한 복잡한 CSS selector 대신 getByRole이나 getByLabel을 제안하는 경우가 많습니다. 작성자는 이를 의견이 강한 linter에 비유합니다. 그러나 어떤 요소와 동작이 제품에서 중요한지는 알지 못합니다. 안정적인 locator 문법을 추천할 수는 있어도, 해당 UI가 어떤 업무 규칙을 표현하고 있으며 어떤 변화가 결함인지까지 판단하지는 못합니다.

■ AI가 놓치는 것은 대부분 도메인 지식에 있습니다

AI는 코드에 드러난 happy path를 중심으로 테스트를 생성합니다. 그래서 “결제 webhook이 두 번 도착하면 어떻게 됩니까?”와 같은 질문은 스스로 제기하지 못합니다. 이런 질문은 새벽 2시에 중복 webhook 장애를 겪어본 사람이 떠올리는 도메인 지식에서 나옵니다. 작성자는 실제로 잡아낸 버그의 대략 80%가 자동으로 생성하기 어려운 테스트에서 나왔다고 말합니다. AI가 만들어주는 테스트 수가 많아지는 것과 중요한 결함을 발견하는 테스트가 늘어나는 것은 같은 일이 아닙니다.

■ 모바일 웹과 Flutter에서는 품질이 크게 떨어집니다

모바일 웹 테스트에서 AI의 약점은 더 분명합니다. 모델이 학습한 데스크톱 웹 테스트 코드가 많기 때문에, viewport별 동작, touch target, 390px 화면에서 sticky header가 클릭을 가리는 상황을 물어도 데스크톱용 해결책을 모바일용이라고 제시하는 경우가 많습니다. 작성자는 반복해서 잘못된 제안을 받아 Playwright 모바일 웹 테스트를 위한 자체 참고 자료를 만들었습니다. device emulation, 실제 touch event, 화면 방향 전환(orientation) 처리는 실제 버그를 경험한 사람이 직접 검토해야 한다고 설명합니다.

Flutter에서는 문제가 더 심합니다. 학습 데이터가 부족해 widget test를 요청하면 두 버전 전에 변경된 API를 사용하는, 겉보기에는 그럴듯한 코드가 나올 수 있습니다. smoke suite를 요청해도 Flutter의 특성을 반영하기보다 웹 테스트 패턴에 Flutter라는 외피만 씌운 결과를 제시합니다. 작성자는 Flutter의 smoke 및 regression 테스트 구조를 거의 전부 직접 설계하고 작성했으며, AI는 각 테스트 내부의 보일러플레이트를 줄이는 정도로만 활용했다고 말합니다. 테스트 스위트의 구조와 범위 결정에는 거의 도움이 되지 않았습니다.

■ self-healing locator는 신중하게 봐야 합니다

작성자는 여러 AI 테스트 도구가 판매하는 self-healing locator도 대부분 마케팅에 가깝다고 평가합니다. locator가 조용히 스스로 복구되면 UI가 변경됐다는 사실을 테스트가 알려주지 않기 때문입니다. 때로는 UI 변경 자체가 버그일 수 있으므로, locator가 자동으로 적응하는 것보다 테스트가 크게 실패해 변경 사실을 알리는 편을 선호합니다. 테스트가 계속 통과하도록 만드는 기능이 테스트의 신뢰성을 높이는 것이 아니라, 오히려 검증 실패를 숨길 수 있다는 문제의식입니다.

■ 작성자가 실제로 사용하는 작업 순서

작성자는 먼저 티켓에 평문으로 테스트 계획을 직접 씁니다. 무엇이 실패해야 하는지, 그리고 왜 그 실패가 중요한지를 정리합니다. 그다음 계획과 기존 page object를 AI에 제공해 테스트 골격을 생성합니다. 생성된 테스트에서는 모든 assertion을 직접 다시 작성하며, 단 하나도 그대로 두지 않습니다. 이후 CI에 보내기 전에 로컬에서 20회 실행합니다. 특정 단계에서 flaky하다면 wait를 추가해 억지로 안정화하기보다 테스트를 삭제하고 처음부터 다시 작성합니다.

특히 사람들이 자주 건너뛰는 단계는 assertion을 다시 쓰는 과정이라고 지적합니다. 생성된 assertion은 어떤 요소가 존재하는지만 확인하는 경우가 많지만, 사람이 작성한 assertion은 그 요소가 올바른 상태와 값을 갖는지 검증합니다. “무언가가 존재합니다”와 “무언가가 정확합니다”는 전혀 다른 역할이며, 테스트의 실질적인 가치는 후자에 있습니다.

■ AI는 테스트 작성 속도는 높이지만 테스트 선택 능력은 높이지 않습니다

결론적으로 AI는 테스트를 작성하는 속도는 높여주지만, 어떤 테스트를 작성해야 하는지 판단하는 능력까지 높여주지는 않습니다. 작성자는 두 번째 능력이 테스트 업무의 핵심이라고 봅니다. QA에 입문하는 사람이 실패 모드와 검증 논리를 배우기 전에 프롬프트 작성부터 익히면, 매우 크고 모두 초록색으로 통과하지만 아무것도 잡아내지 못하는 테스트 스위트를 만들 위험이 있습니다. 이런 스위트는 테스트가 전혀 없는 것보다 나쁠 수 있습니다. 실제로는 보호하지 못하면서도 팀에 잘못된 자신감을 주기 때문입니다.

작성자는 self-healing locator가 실제 프로덕션 스위트에서 유용했던 사례, Flutter나 React Native에서 AI를 활용한 경험, 그리고 모델이 코드를 생성하는 대신 MCP 기반으로 브라우저를 직접 조작하는 방식에 대해서도 질문합니다. 본인은 MCP 방식도 두 번 시도했지만 테스트 코드를 직접 작성하는 것보다 느렸다고 설명합니다. 다만 이것이 해당 방식의 본질적인 한계인지, 자신의 사용 방법이 적절하지 않았기 때문인지는 열어둡니다.

원문: dev.to / 번역·요약: Trawling