Using non-breakable spaces in test method names
테스트 메서드 이름에 줄 바꿈 없는 공백을 사용하기
PHP 테스트 메서드 이름에 일반 공백처럼 보이는 non-breaking space를 넣어 문장처럼 읽히게 만드는 방법을 소개합니다. 팀 내부에서는 1년 넘게 만족스럽게 사용했지만, 터미널 검색과 다른 언어의 식별자 규칙, 오픈소스 협업에서는 혼란을 부를 수 있다는 반론도 나옵니다.
- 주제
AI 요약
PHP에서는 메서드 이름에 일반 공백을 넣을 수 없지만, non-breaking space를 사용하면 공백처럼 보이는 문장형 이름을 작성할 수 있습니다. HTML에서 ` `로 표현하는 문자와 같은 종류이며, 편집기에서는 일반 공백처럼 보이지만 PHP는 식별자에 들어간 다른 문자로 취급합니다. 그래서 `test a user can add a product to a wishlist()`처럼 테스트 이름을 작성해도 유효한 PHP 코드로 동작합니다.
■ camelCase에서 문장형 이름으로
작성자는 과거에 `testAddProductToWishlist()` 같은 camelCase 이름을 사용했습니다. 이후 코딩 스타일에 관한 강연을 접하면서 테스트 메서드에서는 snake_case가 더 읽기 쉽다고 판단했습니다. `test_a_user_can_add_a_product_to_a_wishlist()`처럼 쓰면 테스트가 무엇을 검증하는지 이름만 보고 더 분명하게 파악할 수 있기 때문입니다. 이 방식은 PSR-2의 메서드 이름 규칙에는 맞지 않지만, 팀에서는 테스트 이름의 가독성을 위해 예외를 두기로 했습니다.
그러던 중 팀원 한 명이 가독성을 이유로 PSR-2를 따르지 않을 거라면 non-breaking space를 쓰는 편이 더 읽기 좋지 않겠느냐고 농담했습니다. 팀은 이 제안을 곧바로 표준으로 삼지 않고, 작은 통제 실험으로 일정 기간 사용해 보기로 했습니다. 실제 결과는 긍정적이었습니다. 1년이 넘도록 계속 사용했고, 팀원들은 이 방식에 만족하고 있다고 설명합니다.
■ 테스트 이름을 문장처럼 읽기
팀에서는 테스트 메서드 이름을 코드 식별자라기보다 문장으로 다룹니다. 원문에 제시된 pull request diff에서는 `testProjectMultiVendorProductWithOneDetached()`를 `test product and multivendor product projections are both updated when they are detached()`로 바꿨습니다. camelCase로 압축했던 이름을 자연어 문장으로 풀어 쓰면서, 어떤 조건에서 어떤 결과를 검증하는지 드러냈습니다.
다른 예로 `test very long slugs are truncated()`와 `test there are no projects by default()`가 제시됩니다. 두 번째 테스트의 본문은 `getProjects()` 결과가 비어 있는지 확인하는 `self::assertEmpty()` 호출입니다. 테스트 이름과 검증 코드가 함께 놓였을 때, 이름이 테스트의 의도를 문장으로 설명하는 역할을 한다는 주장입니다.
■ 입력 방법과 개발 도구 호환성
non-breaking space 입력 방법은 운영체제별로 안내합니다. macOS에서는 `Alt + Space`, Ubuntu에서는 `Alt Gr + Space`를 사용합니다. Ubuntu의 `Alt Gr`는 오른쪽 Alt 키입니다.
작성자가 사용한 도구에서는 대체로 문제가 없었다고 합니다. Git, PhpStorm, Sublime Text, GitHub, 과거의 GitLab, PhpStorm 안에서 제공하는 PHPUnit 통합 기능, PhpStorm의 코드 분석 및 리팩터링 도구가 목록에 들어갑니다. PhpStorm에서는 해당 단축키가 Quick Definition 기능을 실행할 수 있으므로 단축키를 끄거나 다른 키로 바꿔야 합니다. Quick Definition은 기본적으로 macOS의 `Cmd + Y`, Windows와 Linux의 `Ctrl + Y`로도 실행하므로 기존 단축키를 제거해도 기능 자체는 남는다고 설명합니다.
Atom과 Visual Studio Code에서는 한때 구문 강조가 어긋나는 문제가 있었습니다. 원문은 Atom의 `atom/language-php#196`과 Visual Studio Code의 `Microsoft/vscode#26992` pull request를 언급하며, 해당 문제가 수정됐다고 적습니다. 작성자의 경험에서는 Git이나 IDE의 실행, 분석, 리팩터링 흐름이 이 이름 형식 때문에 막히지 않았습니다.
■ 팀원과 오픈소스에서의 문제
도구보다 어려운 부분은 사람을 설득하는 일이라고 설명합니다. 새로 합류한 동료는 코드를 처음 읽을 때마다 WTF라는 반응을 보였습니다. 일반적인 코드 관습과 다르기 때문에 처음에는 낯설지만, 팀이 작은 덕분에 주니어와 시니어 개발자 모두 비교적 빠르게 받아들였다고 합니다. 다만 여러 팀이 참여하는 대규모 조직에서는 도입이 더 어려울 수 있다고 선을 긋습니다.
작성자는 일반 공백을 잘못 입력했는지 확인하는 일도 걱정하지 않는다고 말합니다. 눈으로 보면 바로 구분된다는 입장입니다. 다만 이 부분은 커뮤니티에서 반박을 받았습니다. 편집기 안에서는 구별돼도 grep이나 터미널의 다른 텍스트 처리에서는 차이가 눈에 드러나지 않으며, 일반 공백으로 검색하면 일치하지 않을 수 있다는 지적입니다.
폐쇄형 프로젝트와 오픈소스 프로젝트의 차이도 따로 다룹니다. 팀 구성원이 코드와 결정을 함께 관리하는 폐쇄형 프로젝트에서는 실험 결과가 좋으면 유지하고, 좋지 않으면 중단하면 됩니다. 반면 오픈소스 프로젝트에서는 기여자가 설명 없이 낯선 식별자를 만나게 됩니다. 작성자는 현재로서는 기여자가 거의 없을 작은 프로젝트에 먼저 사용하고, 이 실천을 널리 알린 뒤 언젠가 더 자연스럽게 사용할 수 있기를 바란다고 정리합니다.
■ 언어별 적용 범위에 관한 반응
원문은 PHP 사례에 집중합니다. Lobsters 댓글에서는 이 방식이 PHP 밖에서도 통하는지 의문이 제기됐습니다. UAX #31 식별자 규칙을 따르는 JavaScript, C, C++, Rust, Go, Python에서는 이 해킹이 동작하지 않는다는 반응이 나왔습니다. Perl은 UAX #31에 가깝고, Java와 C#은 더 오래된 기본 문자 속성 규칙을 사용한다는 설명도 이어졌습니다. 따라서 이 사례는 여러 언어에 그대로 옮길 수 있는 이름 규칙이라기보다, PHP의 식별자 처리와 팀 도구 환경을 전제로 한 실험으로 읽어야 합니다.
■ Lobsters 반응
• @patryk — 흥미로운 아이디어이지만 snake_case와 비교해 추가되는 가치가 보이지 않습니다. “일반 공백을 잘못 입력했는지 어떻게 알 수 있나요?”라는 질문에 “걱정하지 마세요. 바로 보입니다”라고 답한 부분도 전혀 와닿지 않습니다. 차이는 grep을 하거나 터미널에서 다른 텍스트 처리를 할 때처럼 눈에 보이지 않습니다. `test some thing`으로 grep하면 non-breaking space 버전과 일치하지 않는 문제도 있습니다.
• @kototama — 이 방식이 정말 나쁜 생각이라는 점을 확인해 줍니다. 여러 편집기에서 구문 강조 문제가 있었다는 사실도 그렇습니다. 그런데도 이 일을 끝까지 밀어붙여 글로 발표했습니다. 실험 자체는 흥미롭지만, 솔직히 PHP 커뮤니티 사람들만 이것이 실험 이상의 무언가가 될 수 있다고 생각했을 것 같습니다. 4월 1일 글인가 싶어 작성 날짜까지 확인했지만 그런 내용은 없었습니다.
• @fanf — 이 해킹은 UAX #31 식별자 규칙을 따르는 언어에서는 동작하지 않습니다. JavaScript, C, C++, Rust, Go, Python이 여기에 들어갑니다. UAX #31을 따르지 않는 언어에서도 대부분 동작하지 않습니다. Perl은 UAX #31에 가깝고, Java와 C#은 더 기본적인 문자 속성을 사용하는 오래된 문법을 따릅니다.
• @spc476 — 너무 부정적인 반응들입니다. 하지만 이곳에서는 원래 그런 분위기인 것 같습니다.
원문: mnapoli.fr / 커뮤니티: Lobsters / 번역·요약: Trawling