무인 루프
제품이 다 통과한다는 전제를 깔면 모든 FAIL이 자동화 결함이 됩니다. 공짜 오라클입니다.
사람이 안 보는 동안 밤새 돌리려면 무엇이 필요한가. 여기서 쓴 방법이 좀 특이합니다 — «이미 다 통과하는 걸로 확인된 검사»만 돌립니다. 그러면 실패가 나올 때마다 범인이 하나로 정해집니다.
「공짜 판정관」이라는 발상
자동화를 만들 때 제일 어려운 게 「실패가 났는데, 제품 탓인지 자동화 탓인지 모르겠다」입니다.
둘을 가리려면 사람이 열어 봐야 합니다. 그러면 무인이 아닙니다.
여기서는 그 문제를 처음부터 없앴습니다.
이미 전부 통과하는 걸로 확인된 검사 목록만 돌린다.
그러면 이렇게 됩니다.
| 결과 | 무슨 뜻인가 |
|---|---|
| 통과 | 정상 |
| 실패 | 무조건 자동화 탓 |
사람이 안 봐도 범인이 정해집니다. 그래서 이걸 「공짜 판정관」이라고 적었습니다. 판정해 주는 장치를 따로 만들 필요 없이, 전제 하나가 판정관 역할을 합니다.
끝나는 조건을 «먼저» 적어 뒀습니다
무인으로 돌릴 때 두 번째로 어려운 게 「언제 끝내나」입니다.
안 정해 두면 영원히 돕니다. 아니면 적당히 잘 되는 것 같을 때 사람이 멈춥니다 — 그러면 그게 언제였는지, 어떤 상태였는지가 안 남습니다.
그래서 시작 전에 적었습니다.
전 항목 기계 판정 통과 + 판정 불가 0건. 그게 «두 사이클 연속».
「두 사이클 연속」이 중요합니다. 한 번 잘 된 건 우연일 수 있습니다.
결과
300번 · 9시간 57분 · 사람 없이 · 실패 0 · 뻗음 0.
그런데 이 숫자를 성능 지표로 쓰면 안 됩니다
⚠ 정직하게 적어 둡니다.
「한 단계에 몇 초」 같은 숫자가 나오는데, 그걸 성능이라고 인용하면 안 됩니다.
안에 제가 넣은 «무조건 기다리기»가 섞여 있기 때문입니다. 「여기서 3초 기다려」 같은 걸 제가 넣어 뒀습니다. 그건 제품이 느린 게 아니라 제가 기다리게 한 것입니다.
제 대기 시간과 제품 시간이 섞인 숫자는 어느 쪽 지표도 아닙니다.
무인을 만든 건 성능이 아니라 「복구 구조」였습니다
이게 이 글의 결론입니다.
밤새 안 멈추고 도는 비결이 빠르게 만드는 것일 것 같은데 아니었습니다. 실패가 났을 때 그 실패가 어디까지 번지느냐가 결정했습니다.
| 결과 | |
|---|---|
| 한 곳이 실패하면 전체가 멈춤 | 새벽 2시에 멈춰서 아침까지 8시간 낭비 |
| 한 곳이 실패하면 그 하나만 실패로 적고 다음으로 | 끝까지 돌고, 아침에 실패 목록을 읽음 |
즉 실패를 «국소적으로» 만드는 것이 무인의 조건입니다.
그리고 이건 빠르기와 아무 상관이 없습니다. 느려도 안 멈추면 무인이 되고, 빨라도 한 번 멈추면 그날 밤은 끝입니다.
여기부터는 자세한 기록입니다
이 루프의 설계가 좀 특이하다. 검증 대상 빌드는 이미 전부 통과하는 것으로 확인된 케이스 세트로 돈다.
공짜 오라클
그래서 전제를 하나 세울 수 있다.
제품이 ALL PASS라면, 자동화가 내는 모든 FAIL은 자동화 자신의 결함이다.
정답을 아는 시험지로 자동화를 채점하는 것이다. 자동화 도구를 만들 때 제일 어려운 게 “이 실패가 제품 문제인가 내 문제인가” 인데, 그 질문이 통째로 사라진다.
사이클은 이렇게 돈다 — 돌린다 → 진단한다 → 고친다 → 배운 걸 원장에 적는다 → 다시 돌린다.
진단 없이 재실행하는 것은 금지다. 이 규칙이 없으면 “한 번 더 돌려 보자”가 기본값이 되고, 그러면 간헐적으로 통과하는 케이스가 고쳐지지 않은 채 통계에만 반영된다.
수렴 조건을 미리 적는다
언제 끝나는지를 먼저 정해 뒀다 — 전건 기계 판정 PASS, BLOCKED 0, 그게 두 사이클 연속.
두 사이클 연속이 중요하다. 한 번 전부 통과한 건 우연일 수 있고, 무인 루프에서 우연과 안정의 차이는 반복밖에 없다.
그리고 이걸 미리 안 적으면 끝이 안 난다. 자동화는 항상 조금 더 고칠 데가 있어서, 종료 조건이 없으면 “아직 완벽하지 않다”로 무한히 계속된다.
밤새 돌린 결과
300 사이클 · 9시간 57분 · 무인 · 실패 0 · 크래시 0.
사이클당 검증 지점 26개가 전부 성립했고, 사이클 중앙값은 111.5초(최소 98.8 / 최대 161.8)였다. 배터리는 96%에서 95%로 떨어졌다.
배터리 이야기를 적는 이유가 있다. USB로 물려 놓고 도는데 충전보다 소모가 빠르면 밤샘 자체가 안 된다. 1%면 앞으로 며칠도 돌릴 수 있다는 뜻이다.
이 숫자를 성능 지표로 쓰면 안 된다
⚠ 단계별 수치를 성능 지표로 인용하면 안 된다. 안에 내 스크립트의 고정 대기가 섞여 있다.
“화면 전환에 3.2초”라고 적혀 있어도 그중 2초가 내가 넣은 sleep이면 그건 제품 성능이 아니다. 순수하게 제품 로딩으로 읽을 수 있는 건 인게임 진입 구간 정도고, 로딩 시간을 정식 지표로 쓰려면 계측을 따로 붙여야 한다.
이걸 구분해 적어두지 않으면 반년 뒤에 내가 내 숫자에 속는다. 그리고 더 나쁜 건, 그 숫자를 남에게 보여준 다음이다 — 한 번 인용된 숫자는 출처가 떨어져 나간 채로 돌아다닌다.
무인이 되려면 실패가 국소적이어야 한다
무인 완주를 만든 건 성능이 아니라 복구 구조다.
무증상 정지가 제일 어려웠다. 아무것도 실패하지 않은 채로 멈추니 에러 카운터에 안 잡힌다. 그래서 화면 변화량을 별도 축으로 뒀다 — 변화가 없으면 단계적으로 복구를 시도하다, 그래도 안 되면 끊는다.
끊는 게 중요하다. 사람이 안 보는 실행에서 영원히 기다리는 상태는 실패보다 나쁘다. 실패는 로그에 남고 다음 케이스로 넘어가지만, 대기는 밤새 아무것도 안 하고 아침에 그대로 있다.