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

얼마나 많은 테스트가 너무 많은가?

잘못 테스트된 코드로 작업하는 것이 얼마나 고통스러운지 알고 있습니다. 버그를 수정할 때마다 5개를 더 만듭니다. 그리고 일이 할 때 그렇게 설계되었는지 아니면 우연히 작동했는지 알 수 없습니다.

반면에 당신은 하나의 작은 기능을 제공하기 위해 200개의 테스트처럼 보이는 것을 작성했습니다. 100% 테스트 적용 범위에 도달하려면 이미 작동 중인 코드를 지속적으로 재설계해야 합니다. 가장 잘 테스트된 코드가 점점 지고 있다는 느낌을 지울 수 없습니다. 읽을 수 있습니다. 그리고 무엇보다도 앱에서 지치기 시작합니다.

중간 지점이 있어야 합니다. 그렇다면 얼마나 많은 테스트가 적절한 양입니까?

규칙으로 사용할 수 있는 멋진 숫자가 있다면 좋을 것입니다. 앱 코드보다 두 배 더 많은 테스트 코드 줄, 또는 95% 테스트 적용 범위. 하지만 "95% 테스트 커버리지"라고 말하는 것조차 모호합니다.

적용 범위는 지표가 될 수 있습니다. 잘 테스트된 코드이지만 보증은 아닙니다. 잘 테스트된 코드. 85% 범위의 앱보다 버그가 더 많은 100% 범위의 앱이 있습니다.

따라서 적절한 테스트 양은 숫자에 관한 것이 아닙니다. 대신, 그것은 더 모호하고 정의하기 어려운 것에 관한 것입니다. 효율적인 테스트 .

효율적인 테스트

효율적인 테스트는 최소한의 작업으로 최대의 이점을 얻는 것입니다. 멋지지 않나요?

그러나 더 효율적으로 테스트하는 데 필요한 것이 많이 있습니다. 따라서 특히 크기, 고립, 집중이라는 세 가지 사항에 대해 생각하는 것이 도움이 됩니다.

크기

통합 테스트는 굉장합니다. 실제 사람이 앱을 통해 이동하는 경로를 반영합니다. 실제 환경에서 사용되는 것과 동일한 방식으로 함께 작업하여 모든 코드를 테스트합니다.

그러나 통합 테스트는 느립니다. 길고 지저분할 수 있습니다. 그리고 시스템의 작은 부분 하나를 철저히 테스트하려는 경우 많은 오버헤드가 추가됩니다.

단위 테스트는 더 작습니다. 그들은 더 빨리 달립니다. 작성하는 동안 시스템의 작은 부분만 머리에 저장하면 되므로 생각하기 쉽습니다.

그러나 그들은 또한 가짜 일 수 있습니다. 단위 테스트 내에서 작동한다고 해서 실제 세계에서도 작동하는 것은 아닙니다. (특히 조롱을 많이 하는 경우).

그럼 어떻게 균형을 맞추나요?

단위 테스트는 빠르고 작성하기 쉽기 때문에 많은 비용이 들지 않습니다. 따라서 엣지 케이스 및 복잡한 논리와 같은 것을 테스트하기에 좋은 장소입니다.

테스트를 잘 마친 시스템 조각이 많아도 여전히 그 공백을 채워야 합니다. 이러한 부분이 상호 작용하는 방식과 누군가가 앱을 통해 수행할 수 있는 전체 여정을 테스트해야 합니다. 그러나 대부분의 에지 케이스와 논리는 단위 테스트에서 테스트되기 때문에 이러한 더 복잡하고 느린 통합 테스트 중 일부만 필요합니다.

'테스트 피라미드'라는 아이디어를 듣게 될 것입니다. 여러 단위 테스트의 기반 위에 있는 몇 가지 통합 테스트입니다. 이에 대해 더 알고 싶다면 제 책 Practicing Rails의 세 번째 챕터를 살펴보세요.

격리

하지만 시스템이 복잡한 경우 마주할 수 있는 모든 상황을 처리하기 위해 무한한 테스트가 필요할 수 있습니다. 이는 앱 디자인을 재고해야 한다는 신호일 수 있습니다. 시스템의 일부가 서로 너무 밀접하게 의존하고 있음을 의미합니다.

몇 가지 다른 상태 중 하나일 수 있는 개체가 있다고 가정해 보겠습니다.

case user.type
when :admin
  message = admin_message
when :user
  message = user_message
when :author
  message = author_message
else
  message = anonymous_message
end

if user.preferred_notification_method = :email
  send_email(message)
elsif user.preferred_notification_method = :text
  send_text_message(message)
else
  queue_notification(message) 
end

여기에서 가능한 모든 경로를 테스트하려면 12가지 다른 상황을 테스트해야 합니다.

  1. 사용자는 preferred_notification_method 관리자입니다. 이메일입니다
  2. 사용자는 preferred_notification_method 관리자입니다. 텍스트입니다
  3. 사용자는 preferred_notification_method 관리자입니다. 둘 다
  4. 사용자는 preferred_notification_method 사용자입니다. 이메일입니다
  5. 사용자는 preferred_notification_method 사용자입니다. 텍스트입니다
  6. 사용자는 preferred_notification_method 사용자입니다. 둘 다
  7. 사용자는 preferred_notification_method 작성자입니다. 이메일입니다
  8. 사용자는 preferred_notification_method 작성자입니다. 텍스트입니다
  9. 사용자는 preferred_notification_method 작성자입니다. 둘 다
  10. 사용자가 익명입니다. preferred_notification_method 이메일입니다
  11. 사용자가 익명입니다. preferred_notification_method 텍스트입니다
  12. 사용자가 익명입니다. preferred_notification_method 둘 다

'알림 방식으로 메시지 보내기'와 '사용자 유형에 따라 메시지 생성하기'가 연결되어 있기 때문에 테스트해야 할 경우가 많습니다. 당신은 할 수 있습니다 더 적은 수로 짜낼 수 있지만 명확하지 않으며 버그를 요구할 뿐입니다.

하지만 그것들을 분해한다면 어떻게 될까요?

message = get_message_based_on_user_type(user.type)

send_notification(message, user.preferred_notification_method)

이제 각 부분을 개별적으로 테스트할 수 있습니다.

첫 번째 부분에서는 각 유형의 사용자에 대해 올바른 메시지가 반환되는지 테스트할 수 있습니다.

두 번째 부분에서는 preferred_notification_method 값을 기반으로 주어진 메시지가 올바르게 전송되었는지 테스트할 수 있습니다. .

마지막으로 부모 메서드가 do_stuff_based_on_user_type에서 반환된 메시지를 전달하는지 테스트할 수 있습니다. send_email_or_text로 . 이제 테스트할 상태가 8개 있습니다.

  1. 사용자는 관리자입니다.
  2. 사용자는 사용자입니다
  3. 사용자가 작성자임
  4. 익명 사용자
  5. preferred_notification_method 이메일입니다
  6. preferred_notification_method 텍스트입니다
  7. preferred_notification_method 둘 다
  8. 상위 메소드에 대한 하나의 테스트

여기서는 별도로 테스트할 수 있도록 코드를 분리하여 4개의 테스트를 저장합니다. 두 번째 예에서는 더 적은 수의 테스트로 완료할 수 있다는 것이 훨씬 더 분명합니다. 또한 상태를 더 추가함에 따라 코드를 분할하는 것이 더 나은 아이디어가 되는 방법을 상상할 수 있습니다.

격리와 가독성 사이에서 최상의 균형을 찾기까지는 시간과 연습이 필요합니다. 그러나 적절한 위치에서 종속성을 해제하면 훨씬 적은 수의 테스트로 완료할 수 있습니다.

포커스

앱은 잘 테스트되어야 합니다. 그러나 이것이 앱의 모든 부분이 테스트에서 동일한 양의 관심을 받을 자격이 있다는 것을 의미하지는 않습니다.

100% 테스트 커버리지를 목표로 한다고 해도 모든 것을 테스트하지는 않을 것입니다. 예를 들어 보기의 모든 텍스트 줄을 테스트하지 않거나 업데이트를 위해 10초가 아닌 5초마다 폴링하고 있을 것입니다.

바로 여기에 초점이 맞춰집니다. 더 적은 수의 더 유용한 테스트 작성 그리고 주어진 시간을 가장 잘 보낼 수 있는 곳에서 의식적인 결정을 내립니다.

초점은 맞추기 어려운 또 다른 것입니다. 다음은 가장 중요한 테스트에 집중하는 데 도움이 되는 몇 가지 질문입니다.

  • 이것은 내 앱의 나머지 부분과 얼마나 상호 연결되어 있습니까? 그것이 부서지면 얼마나 많은 다른 조각이 함께 떨어질까요?

  • 이것이 자연스럽게 바뀔 가능성은 얼마나 됩니까? 테스트가 실패하면 버그 때문인가요, 아니면 누군가 UI의 일부 텍스트를 업데이트했기 때문인가요?

  • 이 깨짐의 영향은 무엇입니까? 다른 사람의 신용 카드에 두 번 청구해야 합니까, 아니면 일부 누락된 텍스트만 표시됩니까?

  • 이 부분은 얼마나 자주 사용됩니까? 앱 동작에 중요한가요, 아니면 바닥글 어딘가에 묻힌 정보 페이지인가요?

해서는 안 됩니다. 중요한 부분을 테스트합니다. 하지만 느끼는 앱이 있을 것입니다. 테스트 시간을 잘 활용하면 더 높은 품질을 얻을 수 있습니다.

누군가가 앱을 통해 취할 수 있는 모든 가능한 경로를 테스트하려고 하면 절대 출시되지 않을 것입니다. TDD가 도움이 되지만 모든 테스트 문제를 해결하지는 못합니다.

물론 그렇다고 해서 테스트를 전혀 해서는 안 되는 것은 아닙니다.

테스트 피라미드를 사용하여 테스트를 작게 유지할 수 있습니다. 종속성을 분리하고 중단하여 m * n으로 전환할 수 있습니다. 테스트 케이스를 m + n으로 . 또한 우선 순위를 지정할 수 있으므로 앱의 가장 중요한 부분을 테스트하는 데 더 많은 시간을 할애할 수 있습니다.

그래서 당신은 얼마나 테스트? 앱을 구축할 때 이러한 아이디어를 고려하십니까? 그리고 앱의 어느 부분에 집중해야 하는지 어떻게 알 수 있습니까? 댓글을 남기고 모든 정보를 알려주세요!