Computer >> 컴퓨터 >  >> 프로그램 작성 >> Ruby

내 테스트 범위는 어떻게 되었습니까?

코드를 작성하는 것이 테스트를 작성하는 것보다 훨씬 쉽게 느껴지며 한 줄짜리 방법이 정말 어쨌든 테스트해야합니까? 당연하다! 추가하는 모든 테스트는 개발 시간을 두 배 또는 세 배로 늘리고 다음에 코드를 변경할 때 테스트도 변경해야 합니다. 특히 예상 시간이 얼마 남지 않은 경우에는 낭비인 것 같습니다.

하지만 곧 코드는 테스트의 20%만 적용되며 코드를 변경하면 전체를 무너뜨리지 않고 카드 집의 중간 계층을 교체하려는 것처럼 느껴집니다. 어딘가에서 문제가 발생하여 당시에는 올바른 결정을 내렸지만 결국에는 완전히 유지 관리할 수 없는 코드베이스가 되었습니다.

여기 어떻게 왔어? 테스트가 안전망을 제공하고 자신 있게 리팩토링할 수 있기를 원했습니다. 코드를 개선하는 데 도움이 되었을 것입니다! 그 대신 더 이상 이해하지 못하는 코드에 대한 낮은 테스트 범위로 돌아갔고 테스트를 어떻게든더 어려워졌습니다. 코드를 변경합니다.

이것은 스킬 실패가 아닙니다. 최고의 개발자에게 발생합니다. 과정입니다. 실패. 새로운 기능을 작성하는 방법을 약간 변경하면 테스트 속도를 늦추지 않고 코드를 보호할 수 있습니다. 테스트를 통해 코드를 더 이해하기 쉽고 유연하게 만들 수 있습니다. 테스트되는 모든 경로를 알고 있으므로 자신 있게 코드를 변경할 수 있습니다.

결정을 내릴 필요가 없습니다

결정하려고 키보드 앞에 앉아 있다면 약간의 코드를 테스트해야 하는지 여부는 이미 잘못된 경로로 가고 있습니다. 항상 "Test it!"으로 기본 설정해야 합니다. 너무 시시한 톤 테스트처럼 보이더라도 테스트를 작성하세요.

작성하기 쉬운 코드라면 테스트하기 쉬워야 합니다. 복잡한 코드는 작성한 직후처럼 간단해 보이지 않습니다. 지금부터 6개월이 지나도 그것이 여전히 사소해 보일지 어떻게 알 수 있나요?

하지만 과대평가하고 싶지는 않습니다

거대한 테스트 스위트는 그 자체로 문제가 될 수 있습니다. 실행하는 데 20분이 걸리는 테스트는 항상 실행하지 않을 것이기 때문에 테스트를 전혀 하지 않는 것과 같습니다. (당신은 당신이 할 것이라고 말하지만 당신이하지 않을 것이라는 것을 압니다). 설상가상으로, 취성 테스트가 너무 많으면 리팩토링이 이전보다 더 고통스러워서 하지 않을 것입니다. 대부분의 소설보다 더 긴 방법을 사용하게 될 것입니다.

이것은 나의 이전 요점과 모순되는가? 반드시는 아닙니다. 테스트는 항상 코드의 인터페이스에 초점을 맞춰야 합니다. , 구현이 아님 . 예:

class Cart
  def initialize(item_params)
    @line_items = Array(item_params).map {|item| LineItem.new(item[:name], item[:price])}
  end

  def total
    @line_items.sum(&:price)
  end
end

여기 코드가 Cart 클래스 및 LineItem 수업. 그러나 LineItem은 다른 사람이 사용하는 클래스? Cart의 구현 세부 사항일 경우 , 그리고 외부 세계에 노출되지 않은 경우 실제로 얼마나 많은 테스트가 필요합니까? 통해 테스트하면 안 됩니다. 귀하의 Cart 수업?

리팩토링으로 추출된 클래스는 종종 자체 테스트 스위트가 필요하지 않습니다. 구현 세부정보일 뿐입니다. 이러한 추가 테스트가 필요한 것은 자체적으로 사용할 때만 가능합니다.

공개 인터페이스에 대한 훌륭한 테스트 제품군을 사용하면 모든 테스트를 다시 작성하지 않고도 구현을 변경할 수 있는 유연성이 있습니다. 평균이라도 쓰는 것보다 훨씬 적은 노력으로 이 작업을 수행할 수 있습니다. 개체 구현에 대한 테스트 모음입니다.

테스트 주도 개발로 테스트 비용 상각

첫 번째 섹션에서 모든 것을 테스트해야 한다는 것을 배웠습니다. 두 번째 섹션에서는 publicinterface만 테스트해야 함을 배웠습니다. 이 두 가지 상반된 목표를 하나로 묶는 것은 테스트 주도 개발입니다.

테스트 주도 개발을 통해 테스트는 다음 프로세스에 따라 코드의 설계 및 구현을 주도합니다.

  1. 필요한 코드가 이미 있다고 가정하는 실패한 테스트를 작성하십시오.
  2. 테스트를 통과하는 가장 간단한 코드 구현을 작성합니다.
  3. 중복을 제거하거나 코드를 더 표현력 있게 만들기 위해 리팩토링합니다.
  4. 테스트를 다시 실행하여 여전히 통과하는지 확인합니다.
  5. 1단계로 돌아갑니다.

이 단계를 따르면 모든 것을 테스트하게 됩니다(테스트 실패 없이 코드를 작성해서는 안 되므로). 반면 공용 인터페이스만 테스트합니다(리팩토링 직후에 새 테스트를 작성하지 않기 때문에).

결코 쉽지 않습니다. 그러나 가장 복잡한 코드도 테스트 드라이브할 수 있는 방법이 있습니다.

TDD에는 다음과 같은 몇 가지 부수적인 이점이 있습니다.

  • 보다 유연하고 테스트를 거친 개체 모델(이것이 틀림없이 기본 혜택).
  • 시스템은 기본적으로 테스트 가능하므로 향후 테스트 작성 비용을 절감할 수 있습니다.
  • 개발 프로세스 전반에 걸쳐 테스트 비용을 상각하여 추정치를 더 정확하게 만듭니다.
  • 다음에 무엇을 할지 결정할 필요가 없기 때문에 흐름을 유지합니다.

시작하려면 어떻게 해야 하나요?

시작은 어려운 부분입니다! 테스트 기반 코드를 작성하는 리듬에 빠지면 멈추기 어렵습니다.

다음에 새 기능을 작업할 때 위의 TDD 단계를 따르십시오. 가능한 한 최소한의 작업으로 거의 100%에 가까운 코드 적용 범위를 확보하고 구축할 견고한 기반을 갖게 되며 다음에 코드를 변경해야 할 때 테스트 제품군이 사용자를 보호할 것이라는 완전한 확신을 갖게 될 것입니다. 년도. 또는 요구 사항이 다시 변경되는 오늘 나중에.

작업이 완료되면 이메일을 보내 어떻게 진행되었는지 알려주세요.

간단한 테스트 프로세스를 따르면 간단한 결정을 내리고 버그를 추적하는 시간을 줄이고 고객과 비즈니스의 요구 사항을 해결하는 코드를 작성하는 데 더 많은 시간을 할애할 수 있습니다.