IT

"Arrange-Assert-Act-Assert"내에 삽입?

lottoking 2020. 9. 5. 10:12
반응형

"Arrange-Assert-Act-Assert"내에 삽입?


Arrange-Act-Assert 의 고전적인 테스트 패턴과 관련하여 저는 종종 행동 이전에 반대 주장을 추가하는 것을 발견합니다. 이렇게하면 전달 된 주장이 행동의 결과로 전달되고 있음을 알 수 있습니다.

Red-green-refactor의 빨간색과 유사하다고 생각합니다. 테스트 과정에서 빨간색 막대를 본 경우에만 초록색 막대가 차이를 만드는 코드를 작성했음을 의미합니다. 통과하는 테스트를 작성하면 모든 코드가 만족할 것입니다. Arrange-Assert-Act-Assert와 관련하여 첫 번째 주장이 실패하면 어떤 행동이 최종 Assert를 통과 할 것임을 알고 있습니다. 따라서 실제로 행동에 대한 어떤 것도 확인하지 않습니다.

테스트 가이 패턴을 검사나요? 그 이유는 무엇입니까?

업데이트 설명 : 초기 주장은 기본적으로 최종 주장과 반대입니다. 작동했다는 주장이 아닙니다. Act가 아직 작동하지 않았다는 주장입니다.


이것이 가장 일반적인 방식입니다. 이 기술을 Guard Assertion 이라고 합니다. Gerard Meszaros 의 훌륭한 책 xUnit 테스트 패턴 (강력 권장) 에서 490 페이지에 대한 자세한 설명을 사용할 수 있습니다 .

일반적 으로이 패턴을 직접 사용하지 않습니다. 보장해야하는 것으로 느끼는 전제 조건을 특정하는 테스트를 작성하는 것이 더 있습니다. 모든 테스트는 전제 조건이 실패하면 항상 실패해야하며 이는 다른 모든 테스트에 포함 할 필요가 없음을 의미합니다. 하나의 테스트 케이스가 한 가지만 확인하고 관심 사항을 더 잘 격리 할 수 ​​있습니다.

주어진 테스트 케이스에 대해 무시해야하는 전제 조건이 많을 수 있으므로 Guard Assertion이 두 개 이상 필요할 수 있습니다. 모든 테스트에서이를 반복하는 대신 각 전제 조건에 대해 하나의 테스트 만 있으면 테스트 코드를 더 관리하기 쉽게 작성할 수 있습니다. 그렇게하면 반복 횟수가 기 때문입니다.


Arrange- 가정 -act -assert 로 지정할 수도 있습니다 .

NUnit에는 이에 대한 내용 인 핸들이 있습니다. 예를 들면 다음과 같습니다. http://nunit.org/index.php?p=theory&r=2.5.7


여기에 예가 있습니다.

public void testEncompass() throws Exception {
    Range range = new Range(0, 5);
    assertFalse(range.includes(7));
    range.encompass(7);
    assertTrue(range.includes(7));
}

Range.includes()진실을 반환하기 위해 사용할 수 있습니다 . 나는 구매할 수 있습니다. 아니면 다른 여러 가지 방법으로 잘못 썼습니다. 나는 TDD를 사용하여 실제로 includes()작동하기를 희망하고 기대합니다 . 따라서 첫 번째 주장은 두 번째 주장이 실제로 의미가 있는지 확인하기위한 온 전성 검사입니다.

읽기 자체 assertTrue(range.includes(7));는 "수정 된 범위에 7이 포함됨"이라고 사실입니다. 첫 번째 주장의 맥락에서 읽어 내십시오. "봉투 ()호출 하면 7이 포함 되도록 필자의 주장합니다 . 그리고는 우리가 테스트하는 단위이기 때문에 (작은) 값이라고 생각합니다 있습니다.

나는 내 대답을 받아들이고있다. 다른 많은 사람들이 내 질문을 설정 테스트에 관한 오해했습니다. 약간 다른 것 같아요.


Arrange-Assert-Act-Assert테스트는 항상 두 개의 테스트로 리팩토링 할 수있다 :

1. Arrange-Assert

2. Arrange-Act-Assert

첫 번째 테스트는 조치 단계에서 단계적으로 테스트하고 있다고 주장합니다.

이것은 실패한 것이 준비 또는 행동 단계에서 더 정확한 것을 제공하는 것이 좋습니다. 반면에 Arrange-Assert-Act-Assert더 깊이 단계가 있다고 주장이 실패한 이유와 실패한 이유를 확인하기 위해 정확히 조사해야합니다. 실패한 것은 Arrange 또는 Act였습니다.

또한 테스트를 더 작은 독립 단위로 작은 독립 단위로 더 잘 짜서 단위로 테스트합니다.

마지막으로, 다른 테스트에서 준비 섹션을 볼 때마다이를 공유 도우미 메서드로 가져와야합니다. 테스트가 더 그래야 흥분이 건조 해지고 향후 유지 관리 가 쉬워, 집니다.


테스트중인 작업을 수행하기 전에 상태를 확인하기 위해 "건전성 검사"어설 션을 던지는 것은 오래된 기술입니다. 나는 보통 테스트 스캐 폴딩으로 작성하여 테스트가 내가 기대하는 바를 수행한다는 것을 스스로 증명하고 나중에 테스트 스캐 폴딩으로 복잡한 테스트를 피하기 위해 제거합니다. 거기에 비계를 그대로두면 테스트가 내러티브 역할을하는 데 도움이됩니다.


나는 이미이 기술에 대해 읽었다 – 아마도 당신에게서 – 그러나 나는 그것을 사용하지 않는다; 주로 단위 테스트를 위해 트리플 A 양식에 익숙하기 때문입니다.

이제 호기심이 생기고 몇 가지 질문이 있습니다. 테스트를 어떻게 만들지,이 주장이 실패 할 만들었습니까? 빨강-녹색-빨강-녹색-리 팩터주기를보고거나 추가 추가?

코드를 리팩토링 한 후 가끔 실패합니까? 이것은 당신에게 무엇을 말합니까? 도움이 된 사례를 공유 할 수있을 것입니다. 감사.


실패한 테스트를 조사 할 때 전에이 작업을 수행했습니다.

머리를 많이 긁은 후 "정렬"중에 호출 된 메서드가 제대로 작동하지 않는 것이 원인이라고 판단했습니다. 테스트 실패는 잘못된 것입니다. 편곡 후 Assert를 추가했습니다. 이로 인해 실제 문제를 강조한 곳에서 테스트가 실패했습니다.

테스트의 Arrange 부분이 너무 길고 복잡하면 코드 냄새가 나는 것 같습니다.


일반적으로 나는 "정렬, 행동, 주장"을 매우 좋아하고 그것을 나의 개인 표준으로 사용합니다. 그러나 그것이 나에게 상기시켜주지 못하는 한 가지는 주장이 완료 될 때 내가 배열 한 것을 어긋나게하는 것이다. 대부분의 경우 가비지 수집 등을 통해 대부분의 항목이 자동으로 사라지기 때문에 대부분의 경우 이로 인해 많은 문제가 발생하지 않습니다. 그러나 외부 리소스에 대한 연결을 설정 한 경우 완료되면 해당 연결을 닫고 싶을 것입니다. 당신의 주장으로 또는 당신은 많은 사람들이 다른 사람에게 줄 수 있어야 할 연결이나 중요한 자원을 보유하고있는 서버 나 값 비싼 자원을 가지고 있습니다. TearDown 또는 TestFixtureTearDown을 사용하지 않는 개발자 중 한 명인 경우 특히 중요합니다.하나 이상의 테스트 후 정리합니다. 물론 "Arrange, Act, Assert"는 내가 여는 것을 닫지 못한 것에 대한 책임이 없습니다. 추천 할 "dispose"에 대한 좋은 "A-word"동의어를 아직 찾지 못했기 때문에이 "gotcha"만 언급합니다! 어떤 제안?


나는 지금 이것을하고있다. 다른 종류의 AAAA

Arrange - setup
Act - what is being tested
Assemble - what is optionally needed to perform the assert
Assert - the actual assertions

업데이트 테스트의 예 :

Arrange: 
    New object as NewObject
    Set properties of NewObject
    Save the NewObject
    Read the object as ReadObject

Act: 
    Change the ReadObject
    Save the ReadObject

Assemble: 
    Read the object as ReadUpdated

Assert: 
    Compare ReadUpdated with ReadObject properties

그 이유는 ACT가 ReadUpdated의 읽기를 포함하지 않는 이유는 행위의 일부가 아니기 때문입니다. 행위는 단지 변화하고 저장하는 것입니다. 실제로 어설 션을 위해 ARRANGE ReadUpdated를 사용하고 어설 션을 위해 ASSEMBLE을 호출합니다. 이것은 ARRANGE 섹션의 혼동을 방지하기위한 것입니다.

ASSERT는 어설 션 만 포함해야합니다. 어설 션을 설정하는 ACT와 ASSERT 사이에 ASSEMBLE이 남습니다.

마지막으로, Arrange에서 실패한 경우 이러한 사소한 버그 를 방지 / 찾기위한 다른 테스트가 있어야하므로 테스트가 올바르지 않습니다 . 내가 제시 한 시나리오의 경우 READ 및 CREATE를 테스트하는 다른 테스트가 이미 있어야합니다. "Guard Assertion"을 만들면 DRY를 깨고 유지 관리를 만들 수 있습니다.


Design by Contract 에 대한 Wikipedia의 항목을 살펴보십시오 . Arrange-Act-Assert 삼위 일체는 동일한 개념 중 일부를 인코딩하려는 시도이며 프로그램의 정확성을 증명하는 것입니다. 기사에서 :

The notion of a contract extends down to the method/procedure level; the
contract for each method will normally contain the following pieces of
information:

    Acceptable and unacceptable input values or types, and their meanings
    Return values or types, and their meanings
    Error and exception condition values or types that can occur, and their meanings
    Side effects
    Preconditions
    Postconditions
    Invariants
    (more rarely) Performance guarantees, e.g. for time or space used

이를 설정하는 데 소요되는 노력의 양과 추가되는 가치 사이에는 상충 관계가 있습니다. AAA는 필요한 최소 단계에 대한 유용한 알림이지만 다른 사람이 추가 단계를 생성하지 못하도록 방해해서는 안됩니다.


테스트 환경 / 언어에 따라 다르지만 일반적으로 Arrange 파트의 무언가가 실패하면 예외가 발생하고 테스트에서 Act 파트를 시작하는 대신 표시하지 못합니다. 그래서 저는 보통 두 번째 Assert 부분을 사용하지 않습니다.

또한 Arrange 부분이 매우 복잡하고 항상 예외가 발생하지 않는 경우 일부 메서드 내에서 래핑하고 자체 테스트를 작성하는 것을 고려할 수 있으므로 실패하지 않을 것입니다. 예외 발생).


나는 다음과 같은 것을 생각하기 때문에 그 패턴을 사용하지 않습니다.

Arrange
Assert-Not
Act
Assert

Arrange 파트가 올바르게 작동한다는 것을 알고 있기 때문에 의미가 없을 수 있습니다. 즉, Arrange 파트에있는 모든 항목을 테스트하거나 테스트가 필요하지 않을만큼 간단해야합니다.

답변의 예를 사용하여 :

public void testEncompass() throws Exception {
    Range range = new Range(0, 5);
    assertFalse(range.includes(7)); // <-- Pointless and against DRY if there 
                                    // are unit tests for Range(int, int)
    range.encompass(7);
    assertTrue(range.includes(7));
}

예제의 모든 것을 테스트하려면 다음과 같이 더 많은 테스트를 시도하십시오.

public void testIncludes7() throws Exception {
    Range range = new Range(0, 5);
    assertFalse(range.includes(7));
}

public void testIncludes5() throws Exception {
    Range range = new Range(0, 5);
    assertTrue(range.includes(5));
}

public void testIncludes0() throws Exception {
    Range range = new Range(0, 5);
    assertTrue(range.includes(0));
}

public void testEncompassInc7() throws Exception {
    Range range = new Range(0, 5);
    range.encompass(7);
    assertTrue(range.includes(7));
}

public void testEncompassInc5() throws Exception {
    Range range = new Range(0, 5);
    range.encompass(7);
    assertTrue(range.includes(5));
}

public void testEncompassInc0() throws Exception {
    Range range = new Range(0, 5);
    range.encompass(7);
    assertTrue(range.includes(0));
}

그렇지 않으면 오류 가능성이 너무 많기 때문입니다. 예를 들어 포함 후 범위에는 7 개만 포함됩니다. 범위 길이에 대한 테스트도 있습니다 (임의 값도 포함하지 않았는지 확인하기 위해). 범위에서 5 개를 포함하려는 또 다른 테스트 세트 ... 우리는 무엇을 기대할 수 있습니까? 포함하는 예외 또는 변경되지 않는 범위?

어쨌든, 요점은 당신이 시험하고 싶은 행위에 어떤 가정이 있다면, 그들 자신의 시험에 넣어야한다는 것입니다.


나는 사용한다:

1. Setup
2. Act
3. Assert 
4. Teardown

깨끗한 설정이 매우 중요하기 때문입니다.

참고 URL : https://stackoverflow.com/questions/1021007/should-it-be-arrange-assert-act-assert

반응형

'IT' 카테고리의 다른 글

이미 존재하는 Rails 자동 할당 ID  (0) 2020.09.06
Android 4.2 API 설치 문제  (0) 2020.09.06
내 기능의 시간은 무엇입니까?  (0) 2020.09.05
Java에 버퍼 오버 플로우가 있습니까?  (0) 2020.09.05
ACE vs Boost vs POCO  (0) 2020.09.05