단위 테스트를 사용하여 열거 형의 값을 테스트해야합니까?


15

값이있는 열거 형 만 있고 (Java에서 할 수있는 방법이 없음)이 열거 형이 시스템의 비즈니스 정의의 일부인 경우 하나의 쓰기 단위로 테스트해야합니까?

나는 그들이 단순하고 중복되어 보일 수 있다고해도 그것들이 쓰여 져야한다고 생각하고 있었다. 나는 비즈니스 사양과 관련된 것이 unit / integration / ui / etc와 상관없이 테스트로 명시 적으로 작성되어야한다고 생각한다. 언어의 유형 시스템을 테스트 방법으로 사용하거나 테스트합니다. 비즈니스 관점에서 열거 형 (예 : Java)이 가져야하는 값은 유형 시스템을 사용하여 테스트 할 수 없으므로 단위 테스트가 필요하다고 생각합니다.

이 질문은 내 질문과 같은 문제를 해결하지 않기 때문에이 질문과 비슷 하지 않습니다. 이 질문에는 비즈니스 기능 (savePeople)이 있으며 사람은 내부 구현 (forEach)에 대해 문의합니다. 거기에는 언어 구조 (forEach)를 캡슐화하는 중간 비즈니스 계층 (사람을 구하는 기능)이 있습니다. 여기서 언어 구성 (enum)은 비즈니스 관점에서 동작을 지정하는 데 사용됩니다.

이 경우 구현 세부 사항은 데이터의 "진정한 특성", 즉 (수학적 의미에서) 값의 세트와 일치합니다. 불변의 집합을 사용할 수는 있지만 동일한 값이 여전히 존재해야합니다. 어레이를 사용하는 경우 비즈니스 로직을 테스트하기 위해 동일한 작업을 수행해야합니다. 여기서 수수께끼는 언어 구성이 데이터의 특성과 매우 잘 일치한다는 사실입니다. 자신을 올바르게 설명했는지 확실하지 않습니다.


19
열거 형의 단위 테스트는 정확히 어떤 모양입니까?
jonrsharpe


@jonrsharpe 열거 형 안에있는 값이 예상 한 값이라고 주장합니다. 열거 형의 값을 반복하여 세트 (예 : 문자열)에 추가하여이를 수행합니다. 그 세트를 주문하십시오. 테스트에서 수작업으로 작성한 순서 값 목록과 비교합니다. 일치해야합니다.
IS1_SO

1
@ jonrsharpe, 단위 테스트는 코드로 작성된 "정의"또는 "요구 사항"으로 생각하고 싶습니다. 열거 형의 단위 테스트는 열거 형의 항목 수와 해당 값을 확인하는 것만 큼 간단합니다. 특히 열거 형이 클래스가 아니지만 정수에 직접 매핑 될 수있는 C #에서는 우연히 프로그래밍 하지 않고 값을 보장하여 직렬화 목적에 유용 할 수 있습니다.
Machado

2
IMHO 우주가 올바른지 확인하기 위해 2 + 2 = 4 인 경우 테스트하는 것보다 훨씬 유용하지 않습니다. 열거 형 자체가 아니라 해당 열거 형을 사용하여 코드를 테스트합니다.
Agent_L

답변:


39

값이있는 열거 형 만 있고 (Java에서 할 수있는 방법이 없음)이 열거 형이 시스템의 비즈니스 정의의 일부인 경우 하나의 쓰기 단위로 테스트해야합니까?

아니요, 그들은 단지 상태입니다.

기본적으로 열거 형을 사용한다는 사실은 구현 세부 사항입니다 . 그것은 다른 디자인으로 리팩토링 할 수있는 종류의 것입니다.

완전성에 대한 열거 형 테스트는 표현 가능한 모든 정수가 존재하는지 테스트하는 것과 유사합니다.

그러나 열거가 지원하는 동작을 테스트하는 것이 좋습니다. 다시 말해, 통과하는 테스트 스위트에서 시작하여 단일 열거 형 값을 주석 처리하면 하나 이상의 테스트가 실패해야합니다 (컴파일 오류는 실패로 간주 됨).


5
그러나이 경우 구현 세부 사항은 데이터의 "진정한 특성", 즉 (수학적 의미에서) 값의 세트와 일치합니다. 변경 불가능한 세트를 사용할 수는 있지만 동일한 값이 여전히 존재해야합니다. 배열을 사용하는 경우 비즈니스 로직을 테스트하기 위해 동일한 작업을 수행해야합니다. 여기서 수수께끼는 언어 구성이 데이터의 특성과 매우 잘 일치한다는 사실입니다. 자신을 올바르게 설명했는지 잘 모르겠습니다.
IS1_SO

4
@ IS1_SO — VOU의 한 가지 테스트는 실패 할 것입니다. 이 경우 Enum을 구체적으로 테스트하지 않아도됩니다. 그렇지 않습니까? 어쩌면 당신은 더 간단하게 코드를 모델링 및 데이터의 '본질'을 통해 추상화를 만들 수 있다는 징조가 - 예를 들면 관계없이 한 벌의 카드는 당신이 정말로의 표현을해야합니까, [ Hearts, Spades, Diamonds, Clubs]의 경우 카드가 빨간색 / 검정색 인 경우에만 카드를 사용합니까?
anotherdave

1
@ IS1_SO를 사용하면 많은 수의 오류 코드가 있고 오류가 발생한다고 말할 수 있습니다 null_ptr. 이제 열거 형을 통해 오류 코드가 있습니다. null_ptr오류를 검사 하는 코드는 열거 형을 통해 코드를 조회합니다. 따라서 5(예를 들어) 의 값을 가질 수 있습니다 . 이제 다른 오류 코드를 추가해야합니다. 열거 형이 변경되었습니다 (enum의 맨 위에 새로운 것을 추가한다고 가정 해 봅시다)의 값 null_ptr은 now 6입니다. 이것이 문제입니까? 이제 오류 코드를 반환 6하고를 테스트하십시오 6. 모든 것이 논리적으로 일관성이있는 한, 이러한 변화에도 불구하고 이론적 테스트를 통과해도 괜찮습니다.
Baldrickk

17

열거 형 선언을 테스트하지 않습니다 . 함수 입력 / 출력에 예상되는 열거 형 값이 있는지 테스트 할 수 있습니다. 예:

enum Parity {
    Even,
    Odd
}

Parity GetParity(int x) { ... }

당신은 하지 않습니다 열거 한 후 확인 시험 쓰기 Parity를 정의에게 이름 EvenOdd. 이러한 테스트는 코드에서 이미 언급 한 내용을 반복하기 때문에 무의미합니다. 같은 것을 두 번 말하는 것이 더 정확하지는 않습니다.

당신은 어떻게 확인 쓰기 테스트 GetParity말은 반환 Even, 0 Odd1 등을 위해. 이는 코드를 반복하지 않고 구현과 무관하게 코드의 동작을 확인하기 때문에 유용합니다. 내부 코드 GetParity가 완전히 다시 작성된 경우에도 테스트는 유효합니다. 실제로 단위 테스트의 주요 이점은 코드가 여전히 예상대로 작동하도록하여 코드를 안전하게 다시 작성하고 리팩터링 할 수 있다는 것입니다.

그러나 열거 선언 이 예상되는 이름을 정의 하도록하는 테스트가 있는 경우 나중에 열거를 변경하면 테스트도 변경해야합니다. 이는 단지 두 배의 작업이 아니라 단위 테스트에 대한 이점이 상실되었음을 의미합니다. 코드를 변경하고 동시에 테스트해야하는 경우 버그가 발생하지 않도록 보호 할 수 없습니다.


이 답변을 해결하기 위해 내 질문을 업데이트했습니다. 도움이되는지 확인하십시오.
IS1_SO

@ IS1_SO : 혼란 스럽습니다. 열거 형 값을 동적으로 생성합니까, 아니면 무슨 일이 일어나고 있습니까?
JacquesB

아니요.이 경우 값을 나타내도록 선택된 언어 구조가 열거 형이라는 의미입니다. 그러나 우리가 알다시피 구현 세부 사항입니다. 배열을 선택하거나 Set <> (Java) 또는 값을 나타내는 분리 토큰이있는 문자열을 선택하면 어떻게됩니까? 이 경우 포함 된 값이 비즈니스에 관심이있는 값인지 테스트하는 것이 좋습니다. 그게 내 요점이야 이 설명이 도움이됩니까?
IS1_SO

3
@ IS1_SO : 함수에서 반환 된 열거 형 인스턴스를 테스트하는 데 예상되는 값이 있습니까? 예, 당신은 그것을 테스트 할 수 있기 때문에. 열거 형 선언 자체를 테스트 할 필요는 없습니다.
JacquesB

11

열거 형을 변경하면 코드가 손상 될 위험이있는 경우 C #에서 [Flags] 특성이있는 것은 2와 4 사이의 값을 추가하는 것이 1과 2가 아니라 비트 1과 2이기 때문에 좋은 경우입니다 신중한 품목.

보호 계층입니다.

모든 개발자에게 익숙한 열거 형 실행 코드를 고려해야합니다. 열거 형의 텍스트 표현에 의존하지 않는 것이 일반적이지만 직렬화 지침과 충돌 할 수 있습니다.

나는 사람들이 열거 형 항목의 대문자를 "수정"하고 알파벳순으로 정렬하거나 다른 논리적 그룹으로 분류하여 다른 비트의 나쁜 코드를 깨뜨린 것을 보았습니다.


5
열거 형의 숫자 ​​값이 데이터베이스에 저장 될 때와 같이 어디에서나 사용되는 경우 순서를 바꾸면 (마지막 값 앞에 제거 또는 삽입 포함) 기존 레코드가 유효하지 않게 될 수 있습니다.
stannius

3
+1,이 답변은 과소 평가되었습니다. 열거 형이 직렬화, 외부 단어가있는 입력 인터페이스 또는 비트 구성 가능한 정보의 일부인 경우 각 버전의 시스템에서 일관성을 테스트해야합니다. 적어도 이전 버전과의 호환성이 걱정된다면 보통 좋은 것입니다.
Machado

11

아니요, 열거 형에 유효한 모든 값이 포함되어 있는지 확인하는 테스트는 본질적으로 열거 형 선언을 반복하는 것이 없습니다. 언어가 의미없는 테스트 인 열거 형 구문을 올바르게 구현하는지 테스트하는 것입니다.

즉, 열거 형 값에 따라 동작을 테스트해야합니다. 예를 들어, 열거 형 값을 사용하여 엔티티를 json 등으로 직렬화하거나 값을 데이터베이스에 저장하는 경우 열거 형의 모든 값에 대한 동작을 테스트해야합니다. 이렇게하면 열거 형이 수정되면 적어도 하나의 테스트가 실패해야합니다. 어쨌든 테스트 할 것은 열거 형 선언 자체가 아니라 열거 형 주위의 동작입니다.


3

코드는 열거 형의 실제 값과 독립적으로 올바르게 작동해야합니다. 이 경우 단위 테스트가 필요하지 않습니다.

그러나 열거 형 값을 변경하면 문제가 발생하는 코드가있을 수 있습니다. 예를 들어, 열거 형 값이 외부 파일에 저장되어 있고 열거 형 값을 변경 한 후 외부 파일을 읽은 후 잘못된 결과가 나타납니다. 이 경우 열거 형 근처에 누군가에게 값을 수정하지 말라고 경고하는 큰 주석이 있으며 숫자 값을 확인하는 단위 테스트를 작성하는 것이 좋습니다.


1

일반적으로 열거 형에 하드 코딩 된 값 목록이 있는지 확인하는 것만으로는 가치가 없습니다. 다른 답변에서 말했듯이 테스트와 열거 형을 함께 업데이트해야하기 때문입니다.

한 모듈이 다른 두 모듈의 열거 형 유형을 사용하고 그 사이에 매핑 한 경우가있었습니다. (열거 중 하나에는 추가 논리가 있었고, 다른 하나는 DB 액세스를위한 것이 었으며, 둘 다 서로 분리되어야하는 종속성이있었습니다.)

이 경우 소스 열거 형의 모든 열거 형 항목이 대상 열거 형에도 존재하므로 매핑이 항상 작동하는지 확인하는 테스트 (매핑 모듈에서)를 추가했습니다. (어떤 경우에는 다른 방법으로도 확인했습니다.)

이렇게하면 누군가 열거 형 항목 중 하나에 열거 형 항목을 추가하고 다른 항목에 해당 항목을 추가하는 것을 잊었을 때 테스트가 실패하기 시작했습니다.


1

열거 형은 단순히 유한 한 유형이며 사용자 정의 (유용한 의미있는) 이름이 있습니다. 열거 형에는 값이 하나만 포함될 수 있습니다 ( void포함 된 것만 포함) null(일부 언어는 이것을 호출 unit하고 요소 void없는 열거 형 의 이름 을 사용합니다 !). 이 같은 두 개의 값을 가질 수 bool있다있는을 false하고 true. 이 같은 세 가지가있을 수 colourChannelred, greenblue. 등등.

두 열거 형의 값이 같은 경우 "등방성"입니다. 즉, 모든 이름을 체계적으로 바꾸면 다른 이름 대신 다른 이름을 사용할 수 있으며 프로그램은 다르게 동작하지 않습니다. 특히 테스트 는 다르게 작동하지 않습니다!

예를 들어, result함유 win/ lose/을 draw위의 동형 colourChannel우리가 예를 들어 대체 할 수 있기 때문에, colourChannelresult, redwin, greenlosebluedraw같은 우리가 그렇게로서, 그리고 사방 (생산자와 소비자, 파서 및 serialisers, 데이터베이스 항목, 로그 파일 등 ) 프로그램에 변화가 없습니다. colourChannel우리가 쓴 " 테스트"는 colourChannel더 이상 없어도 통과 할 것입니다!

또한 열거 형에 둘 이상의 값이 포함되어 있으면 항상 해당 값을 재 배열 하여 동일한 수의 값을 가진 새 열거 형을 얻을 수 있습니다. 값의 개수가 변경되지 않았으므로 새로운 배열은 이전 배열과 동형이되므로 모든 이름을 바꿀 수 있고 테스트는 여전히 통과됩니다 ( 정의를 바꿀 수는 없습니다 . 여전히 모든 사용 사이트를 끄십시오).

이것이 의미하는 것은, 기계에 관한 한 열거 형은 "구별 할 수없는 이름"이며 그 밖의 것은 없다는 것 입니다. 열거 형으로 할 수있는 유일한 것은 두 값이 같은지 (예 : red/ red) 또는 다른지 (예 : red/ blue) 를 분기하는 것 입니다. 이것이 '단위 테스트'가 할 수있는 유일한 것입니다.

(  red == red  ) || throw TestFailure;
(green == green) || throw TestFailure;
( blue == blue ) || throw TestFailure;
(  red != green) || throw TestFailure;
(  red != blue ) || throw TestFailure;
...

@ jesm00이 말했듯이 이러한 테스트는 프로그램이 아닌 언어 구현을 확인하는 것입니다. 이러한 테스트는 결코 좋은 생각이 아닙니다. 언어 구현을 신뢰하지 않더라도 테스트를 올바르게 실행한다고 신뢰할 수 없으므로 외부 에서 테스트해야합니다!

이것이 이론입니다. 연습은 어떻습니까? 열거 형 의이 특성화의 주요 문제는 '실제 세계'프로그램이 거의 포함되지 않는다는 것입니다. 우리는 레거시 버전, 원격 / 임베디드 배포, 히스토리 데이터, 백업, 라이브 데이터베이스 등을 가지고 있으므로 절대로 '전환'할 수 없습니다. 일부 사용을 놓치지 않고 이름의 모든 발생.

그러나 그러한 것은 열거 자체의 '책임'이 아닙니다. 열거를 변경하면 원격 시스템과의 통신이 중단 될 수 있지만 반대로 열거를 변경하여 이러한 문제를 해결할 수 있습니다 !

이러한 시나리오에서 열거 형은 청각 적입니다. 한 시스템 이 이런 식 이어야 하고 다른 시스템 그런 식이어야 한다면 어떻게해야합니까? 얼마나 많은 테스트를 작성하든 상관 없습니다. 여기서 중요한 범인은 입력 / 출력 인터페이스이며, "인터 프리트가 선택하는 정수"가 아니라 잘 정의 된 형식을 생성 / 소비해야합니다. 따라서 실제 솔루션은 i / o 인터페이스테스트하는 것 입니다. 단위 테스트를 통해 예상 형식을 구문 분석 / 인쇄하는지 확인하고 통합 테스트를 통해 형식이 실제로 다른 쪽에서 승인되는지 확인합니다.

우리는 열거 형이 '충분히 충분히 운동'되는지 궁금해 할 수 있지만이 경우 열거 형은 다시 빨간 청어입니다. 우리가 실제로 우려하는 것은 테스트 스위트 자체 입니다. 여기서 몇 가지 방법으로 신뢰를 얻을 수 있습니다.

  • 코드 범위는 테스트 스위트에서 나오는 다양한 열거 형 값이 코드의 다양한 분기를 트리거하기에 충분한 지 여부를 알려줍니다. 그렇지 않은 경우, 발견되지 않은 분기를 트리거하는 테스트를 추가하거나 기존 테스트에서 더 다양한 열거를 생성 할 수 있습니다.
  • 속성 검사는 코드의 다양한 브랜치가 런타임 가능성을 처리하기에 충분한 지 알려줍니다. 예를 들어 코드가 만 처리 red하고로만 테스트하면 red100 % 적용 범위를 갖습니다. 속성 검사기는 테스트를 위해 잊어 버린 greenblue값 생성과 같은 어설 션에 대한 반례를 생성하려고 시도합니다 .
  • 우리의 주장이 사실인지 돌연변이 시험은 우리를 알 수 있습니다 확인 단지 가지를 다음과 차이점을 무시하기보다는, 열거합니다.

1

아니요. 단위 테스트는 테스트 단위를위한 것입니다.

객체 지향 프로그래밍에서 유닛은 종종 클래스와 같은 전체 인터페이스이지만 개별 메소드 일 수 있습니다.

https://ko.wikipedia.org/wiki/Unit_testing

선언 된 열거 형에 대한 자동 테스트는 개발자가 작성한 코드의 논리가 아니라 언어 및 언어의 무결성을 테스트하는 것입니다. 열거 형을 선언하는 코드는 테스트 할 코드뿐만 아니라 문서의 역할을하기 때문에 유용한 목적으로 사용되지 않습니다.


0

코드의 관찰 가능한 동작, 메소드 / 함수 호출이 관찰 가능한 상태에 미치는 영향을 테스트해야합니다. 코드가 올바른 작업을 수행하는 한 다른 테스트는 필요하지 않습니다.

클래스가 실제로 존재하거나 클래스에 실제로 필요한 메소드와 속성이 있다고 명시 적으로 주장하지 않는 것처럼 열거 형에 원하는 항목이 있다고 명시 적으로 주장 할 필요는 없습니다.

실제로 동작을 테스트하면 테스트에 포함 된 클래스, 메서드 및 값이 존재한다는 것을 암시 적으로 주장하므로 명시 적으로 어설 션 할 필요가 없습니다.

코드가 올바른 작업을 수행하기 위해 의미있는 이름이 필요하지는 않습니다. 이는 사람들이 코드를 읽는 데 편리합니다. 당신은 열거 같은 값을 사용하여 코드가 작동 할 수있다 foo, bar...과 같은 방법을 frobnicate().

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