자신을 반복하는 것은 괜찮습니다(특히 테스트에서)

3811 단어 programmingtesting
Ruby 및 JavaScript와 같은 언어로 단위 테스트를 작성할 때 잘 테스트된 함수는 코드보다 더 많은(아마도 2-3배 더 많은) 단위 테스트의 총 라인을 갖습니다.

우리는 이 모든 단위 테스트 코드를 가지고 있기 때문에 여러 번 반복되는 라인을 발견하면 모든 라인을 제거하고 도우미 함수 또는 테스트 래퍼를 만들고 싶을 수 있습니다. 그러나 반복을 피하려는 이러한 욕망은 우리를 쉽게 Wrong Abstraction 로 이끌 수 있습니다.

잘못된 추상화는 어디에서나 문제이지만 단위 테스트에서는 특히 나쁩니다. 시간이 지나면서 5개의 인수를 사용하고 여러 개의 중첩된 if 문을 포함하는 매끄럽고 작은 도우미 함수가 자체 테스트를 거치지 않기 때문입니다. . 코드를 테스트하려는 코드에 자체 논리( if 문, switch/case 블록 등)이 있는 경우 테스트 중인 코드를 제대로 테스트하고 있는지 여부를 알 수 없습니다.

중요한 것은 "DRY"(Don't Repeat Yourself)가 그 자체로 최종 목표가 아니라 읽기 가능하고 유지 관리 가능한 코드를 추구하는 데 사용하는 하나의 도구라는 것입니다. 코드를 건조하면 실제로 읽고 유지 관리하기가 더 어려워지면 목적을 달성하지 못하는 것입니다.

예를 들어:

// This example is in Jasmine; feel free to imagine it in
// Jest, Mocha, RSpec, Cucumber, etc.
describe('restartServer', function () {
  it('resets keepalive', async function () {
    server.stop.and.resolveWith();
    server.start.and.resolveWith();
    await instance.restartServer();
    expect(server.stop).toHaveBeenCalled();
    expect(server.start).toHaveBeenCalled();
    expect(instance.keepalive).toEqual(0);
  });
});


제 생각에는 서버 재시작 동작의 다양한 측면을 테스트하는 이와 같은 단위 테스트가 20개 더 있더라도 일반적으로 해당 스텁 라인을 시도하고 건조시키는 것은 가치가 없습니다.

여러분 중 일부에게는 이것이 일반적인 코딩 관행에 직면하여 날아가는 것처럼 보일 수 있지만 몇 가지 일반적인 상황을 살펴보겠습니다.
  • 단위 테스트가 예기치 않게 실패합니다. 개발자는 문제의 테스트로 이동합니다. 이 테스트를 실행하는 데 필요한 모든 것이 앞에 있는 화면에 있습니다. 다른 코드 파일이나 함수를 건너뛰지 않아도 됩니다.
  • 누군가가 함수에 한 줄의 코드를 추가했는데 새로운 단위 테스트가 필요합니다. 기존 테스트를 복사하여 붙여넣고 약간 조정하면 작업이 완료됩니다.
  • 누군가가 함수에 대한 논리 변경을 수행하여 경우에 따라 stop() 호출을 건너뜁니다. 단위 테스트의 절반은 중단되고 나머지는 계속 작동하며 개발자는 이러한 기대치를 수정하여 중단된 단위 테스트를 수정합니다. (어떤 일이 일어나지 않는가? 전형적인 잘못된 추상화 패턴: Big Helper Function에 또 다른 부울 인수를 추가하고 또 다른 기대를 조건부로 만드는...)

  • 내 입장은 거의 항상 단위 테스트 코드를 "DRY"하려고 하면 가독성과 유지 관리성에 상당한 단점이 따른다는 것입니다. 테스트 대상 코드에서 제공하는 일반적인 이점에 거의 반비례합니다.

    어떻게 생각해?

    표지 이미지 by Ben Allan .

    좋은 웹페이지 즐겨찾기