TDD 디버깅

사진 작성자Bart ChristiaanseUnsplash
우리는 모두 다음과 같은 상황을 겪었다. 누군가가 잘못을 보고했을 때, 당신은 첫 번째 커피를 마시고 있었다.첫 번째 반응은 프로젝트를 실행하는 것일 수도 있습니다. 로그를 입력해서 데이터를 보고 무슨 일이 일어났는지 알아보려고 합니다.
만약 당신이 80퍼센트의 개발자처럼 (이 숫자는 내가 작성한 것이다) 당신은 어떤 유형의 테스트도 하지 않는다. 당신은 기본적으로 약간의 조정을 하고 있다. 당신이 문제를 복구할 때 다른 것이 문제가 발생하지 않기를 바란다. 만약 이런 상황이 발생한다면 당신은 결국 예상보다 많은 시간을 들일 것이다.

명확하게 말하자면, 나는 여기서 너희들에게 테스트와 위대한 코드 커버율이 있어야 한다고 말하지 않았다. 항목마다 다르다. 테스트를 하지 않는 이유가 한 가지가 아니다.아마도 당신은 이 기능을 개발하지 않았을 것이다. 당신은 이 행위가 너무 간단해서 테스트가 너무 번거롭거나, 돌진이 끝나기 전에 서둘러 끝내야 한다고 생각했을 것이다.
어떤 이유로든지 이 문제는 당신에게 두 번째 테스트를 추가할 기회를 주었고, 이것은 당신과 미래의 개발자들에게 많은 시간을 절약할 것이다.나는 테스트를 집안의 스모그 탐지기라고 상상하는 것을 좋아한다. 벌레는 화재이다. 화재를 진압할 수 있을 것이다. 그러나 스모그 탐지기가 충분하지 않으면 다른 곳에서 화재가 발생하고 있는지 알 수 없다. 이미 늦었다.

사진 작성자Adam WilsonUnsplash

하나의 진실한 예


한 팀 동료는 우리의 폼에 있는 URL 입력이 잘못된 URL을 받아들인 문자열을 입력했다고 보고했다.기본적으로 foobarhttps://google.com,fizbuzz와 같은 내용을 입력하고 검증을 통과할 수 있습니다.우리는 방법을 강구하여 범인을 찾았다.
function validUrl(url) {
  const regex = /(^$)|((http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_+.~#?&/=]*))/g;
  const found = url.match(regex);
  if (found === null) {
    return false;
  }
  return true;
}
어떤 사람들은 기본적으로 어느 곳에서 정규 표현식을 복사/붙여넣었고 일부 URL과 비 URL을 대상으로 테스트를 했는데 그것이 유효하다고 여겼다.정규 표현식regextester.com을 삽입한 후에 이 모델은 엄격하지 않고 포함 모델임이 분명하다.

정규 표현식을 약간 조정한 후에 우리는 이를 더욱 엄격하게 하는 방법을 찾았는데 결과는 다음과 같다./(^((http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_+.~#?&/=]*))$)/g우리는 레지스터 도구에서 그것을 테스트했는데, 매우 효과적인 것 같다.

지금 우리는 그 줄의 코드를 교체해서 발송하기만 하면 된다. 그렇지?틀렸어!
코드 변경을 수행하기 전에 작업해야 하는 장면에 대한 몇 가지 테스트를 작성합니다.
describe("validUrl", () => {
  it("should not return errors with an empty string", () => {
    const actual = validUrl("");
    const expected = true;
    expect(actual).equal(expected);
  });
  it("should not return errors with a well formed URL", () => {
    const actual = validUrl("https://google.com");
    const expected = true;
    expect(actual).equal(expected);
  });
  it("should return an error with something that is not a url", () => {
    const actual = validUrl("not-a-url");
    const expected = false;
    expect(actual).equal(expected);
  });
  it("should return an error if empty spaces ares used", () => {
    const actual = validUrl("  ");
    const expected = false;
    expect(actual).equal(expected);
  });
});
코드를 읽거나 이해하지 않으려면 다음을 확인합니다.
  • 빈 문자열을 받았을 때 유효합니다 (우리는 RequiredValidUrl 함수를 가지고 있습니다. 그렇지 않을 때)
  • 올바른 형식의 URL은 유효합니다
  • URL이 아닌 내용은false
  • 로 돌아가야 합니다.
  • 공백 사용 불가
  • 새 실패 테스트 용례가 추가되었습니다. 추가 텍스트가 있는 URL은 실패할 것입니다.
    it("should return an error when a url has extra text", () => {
      const actual = validUrl("somethinghttp://google.com,other-thing");
      const expected = false;
      expect(actual).equal(expected);
    });
    
    이것은 codepen의 카드입니다. 따라보셔도 됩니다.
    그리고 우리는 테스트를 실행했다. 마지막 테스트를 제외하고는 모두 통과했다. 왜냐하면 우리는 정규 표현식을 바꾸지 않았기 때문이다. 이것은 매우 좋다. 왜냐하면 우리는 우리의 가설을 확인했기 때문이다. 현재 TDD 순환에 빨간색이 나타났기 때문이다.

    테스트를 예상대로 통과하지 못했습니다.

    TDD 주기
    우리는 정규 표현식을 새 /(^((http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_+.~#?&/=]*))$)/g 로 바꾸었다.
    이것은 우리가 유일하게 오류를 복구해야 한다고 생각하는 것이다. 그리고 우리는 다시 테스트를 실행하여 모든 테스트가 통과되기를 기대했지만, 그것들은 통과하지 못했다.

    놀랍게도 우리의 정규 표현식은 현재 매우 엄격해서 빈 문자열을 사용할 수 없지만, 우리의 스모그 탐지기는 우리가 눈치채지 못한 화재를 내는 것을 막는다.이것은 우리, 테스트 인원, 프로젝트 매니저에게 시간 낭비이며, 최악의 경우, 그것을 배치하면 발사를 막거나 재난을 초래할 수 있다.
    우리는 가장자리 상황을 처리해야 하기 때문에 정규 표현식을 계속 조정하는 것이 아니라 처음부터 단락을 만들기로 결정했다.
    if (!url) {
      // empty string should be valid
      return true;
    }
    

    지금 우리는 초록색이야!우리는 계속해서 재구성해서 우리의 변경 사항을 더욱 자신 있게 보낼 수 있다.
    물론 이것은 묘약이 아니기 때문에 더 많은 변두리 사례나 수요 변화가 있을 수 있다.이렇게 하면, 이러한 상황이 발생할 때, 귀하나 다른 유지보수 프로젝트를 필요로 하는 개발자는 스모그 탐지기를 계속 추가할 수 있고, 그것들의 변경이 낡은 화재에 다시 불을 붙이는 것이 아니라 화재를 진압하고 있다고 확신할 수 있다.

    좋은 웹페이지 즐겨찾기