정적 유형의 기능 코드 단위 테스트


15

나는 사람들에게 물어보고 싶었습니다.이 경우 haskell, scala, ocaml, nemerle, f # 또는 haXe로 작성된 정적 형식의 기능 코드를 단위 테스트하는 것이 합리적입니다 (마지막에 관심이있는 것이지만 원했습니다. 더 큰 공동체에 대한 지식을 활용하십시오).

나는 이것을 이해하기 때문에 이것을 묻습니다.

  • 단위 테스트의 한 측면은 사양을 실행 가능한 형식으로 유지하는 것입니다. 그러나 공식화 된 스펙을 언어 시맨틱에 직접 맵핑하는 선언적 스타일을 사용할 때 실제로 스펙을 별도의 방식으로 실행 가능한 형태로 표현하는 것이 가능 합니까?

  • 단위 테스트의보다 분명한 측면은 정적 분석을 통해 확인할 수없는 오류를 추적하는 것입니다. 유형 안전 기능 코드는 정적 분석기가 이해하는 것과 매우 근접한 코드를 작성하는 데 유용한 도구이므로 많은 안전을 정적 분석으로 전환 할 수 있습니다. 그러나 코드에서 (좌표) x대신 사용 하는 것과 같은 간단한 실수는 y다루지 못합니다. 테스트 코드를 작성하는 동안 OTOH와 같은 실수가 발생할 수도 있으므로 노력할만한 가치가 있는지 잘 모르겠습니다.

  • 단위 테스트에는 중복성이 도입되므로 요구 사항이 변경 될 때 요구 사항을 구현하는 코드와이 코드를 다루는 테스트를 모두 변경해야합니다. 물론이 오버 헤드는 일정하기 때문에 실제로 중요하지 않다고 주장 할 수 있습니다. 실제로 Ruby와 같은 언어에서는 실제로 이점과 비교되지 않지만 정적 형식의 함수형 프로그래밍이 많은지면 단위 ​​테스트를 대상으로하는 방법을 고려할 때 페널티없이 간단하게 오버 헤드를 줄일 수있는 것처럼 느껴집니다.

이것으로부터 나는이 프로그래밍 스타일에서 단위 테스트가 다소 쓸모 없다고 추론 할 것이다. 물론 그러한 주장은 종교적 전쟁으로 만 이어질 수 있으므로 간단한 질문으로 요약하겠습니다.

이러한 프로그래밍 스타일을 사용할 때 단위 테스트를 어느 정도까지 사용하고 왜 (코드에 대해 어떤 품질을 얻으려고합니까?) 또는 다른 방법으로 : 정적 분석기가 적용 하는 정적 유형의 기능 코드 단위를 검증 할 수있는 기준이 있으므로 단위 테스트 적용 범위가 필요하지 않습니까?


4
그건 그렇고, QuickCheck을 시도하지 않았다면 분명히해야합니다.
Jon Purdy

scalacheck.org 는 스칼라에 해당합니다
V-Lamp

답변:


8

단위 테스트의 한 측면은 사양을 실행 가능한 형식으로 유지하는 것입니다. 그러나 공식화 된 스펙을 언어 시맨틱에 직접 맵핑하는 선언적 스타일을 채택 할 때 실제로 스펙을 별도의 방식으로 실행 가능한 형태로 표현하는 것이 가능합니까?

함수 선언에 직접 매핑 할 수있는 사양이 있다면 괜찮습니다. 그러나 일반적으로 두 가지 완전히 다른 추상화 수준입니다. 단위 테스트는 함수를 작업하는 동일한 개발자가 화이트 박스 테스트로 작성한 단일 코드 조각을 테스트하기위한 것입니다. 사양은 일반적으로 "이 값을 여기에 입력하고이 버튼을 누르면 이것이 발생합니다"와 같습니다. 일반적으로 이러한 사양은 개발 및 테스트 할 기능이 훨씬 더 많습니다.

그러나 코드에서 y 대신에 x를 사용하는 것과 같은 간단한 실수 (좌표)는 다루지 않습니다. 그러나 테스트 코드를 작성하는 동안 이러한 실수가 발생할 수도 있으므로 노력할만한 가치가 있는지 잘 모르겠습니다.

당신의 오해는 여기서 단위 테스트가 실제로 코드에서 버그를 찾기위한 것이라고 생각합니다. 적어도 사실이 아닙니다. 나중에 코드가 진화 할 때 버그가 발생하지 않도록하기 위해 만들어졌습니다. 따라서 함수를 처음 테스트하고 단위 테스트를 수행 한 후 ( "x"및 "y"가 올바르게 배치 된 경우) 리팩토링하는 동안 y 대신 x를 사용하면 단위 테스트에 표시됩니다.

단위 테스트에는 중복성이 도입되므로 요구 사항이 변경 될 때 요구 사항을 구현하는 코드와이 코드를 다루는 테스트를 모두 변경해야합니다. 물론이 오버 헤드는 일정하기 때문에 실제로 중요하지 않다고 주장 할 수 있습니다. 실제로 Ruby와 같은 언어에서는 실제로 이점과 비교되지 않지만 정적 형식의 함수형 프로그래밍이 많은지면 단위 ​​테스트를 대상으로하는 방법을 고려할 때 페널티없이 간단하게 오버 헤드를 줄일 수있는 것처럼 느껴집니다.

엔지니어링에서 대부분의 안전 시스템은 중복성을 사용합니다. 예를 들어, 차에서 두 번의 휴식, 스카이 다이버를위한 중복 낙하산 등이 동일한 아이디어가 단위 테스트에 적용됩니다. 물론 요구 사항이 변경 될 때 변경해야 할 코드가 많으면 단점이 될 수 있습니다. 따라서 특히 단위 테스트에서 DRY를 유지하는 것이 중요합니다 ( "반복하지 마십시오"원칙을 따르십시오). 정적으로 유형이 지정된 언어에서는 약한 유형의 언어보다 단위 테스트가 적어야합니다. 특히 "공식적인"테스트는 필요하지 않을 수 있습니다. 이는 중요한 것을 테스트하는 중요한 단위 테스트에 대해 더 많은 시간을 할애 할 수 있기 때문에 좋은 것입니다. 그리고 정적 유형 때문에 단위 테스트가 필요하지 않다고 생각하지 마십시오. 리팩토링 중에 버그를 도입 할 여지가 여전히 많습니다.


5

단위 테스트의 한 측면은 사양을 실행 가능한 형식으로 유지하는 것입니다. 그러나 공식화 된 스펙을 언어 시맨틱에 직접 맵핑하는 선언적 스타일을 채택 할 때 실제로 스펙을 별도의 방식으로 실행 가능한 형태로 표현하는 것이 가능합니까?

사양을 유형 제약 조건으로 완전히 표현할 가능성은 거의 없습니다 .

이러한 프로그래밍 스타일을 사용할 때 단위 테스트를 어느 정도까지 사용하고 왜 (코드에 대해 어떤 품질을 얻으려고합니까?)

실제로이 스타일의 주요 이점 중 하나는 순수한 기능이 단위 테스트를보다 쉽게 ​​수행 할 수 있다는 것입니다.

함수의 스펙 (또는 그 일부)은 리턴 값을 인수와 관련한 특성 으로 표현할 수 있습니다 . 이 경우 QuickCheck (Haskell의 경우) 또는 ScalaCheck (Scala의 경우)를 사용하면 이러한 속성을 언어의 표현으로 기록하고 임의 입력을 유지하는지 확인할 수 있습니다.


1
QuickCheck에 대한 좀 더 자세한 내용 : 기본 개념은 "속성"(코드의 불변)을 작성하고 잠재적 입력을 생성하는 방법을 지정하는 것입니다. 그런 다음 빠른 검사는 수많은 임의의 입력을 생성하고 모든 경우에 불변 값을 유지합니다. 단위 테스트보다 더 철저합니다.
Tikhon Jelvis

1

단위 테스트는 코드를 사용하는 방법의 예와 코드가 왜 유용한 지에 대한 설명으로 생각할 수 있습니다.

Bob Concle이 John Conway의 "Game of Life"에서 나와 어울릴 만큼 친절했던 예가 있습니다. 이런 종류의 운동에는 훌륭한 운동이라고 생각합니다. 대부분의 테스트는 전체 시스템으로 전체 게임을 테스트하지만 첫 번째 테스트는 하나의 함수 (셀 주위의 이웃을 계산하는 함수) 만 테스트합니다. 모든 테스트가 선언적인 형태로 작성되었으며, 우리가 찾고있는 행동이 명확하게 설명되어 있음을 알 수 있습니다.

함수에 사용 된 함수를 조롱 할 수도 있습니다. 함수 (종속성 주입과 동등한 기능)에 전달하거나 Brian Marick 's Midje 와 같은 프레임 워크를 사용하여 전달합니다 .


0

그렇습니다. 단위 테스트는 이미 정적으로 유형화 된 기능 코드와 관련이 있습니다. 간단한 예 :

prop_encode a = (decode . encode $ a) == a

prop_encode정적 유형으로 강제 할 수 있습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.