>source

자체적으로 실행할 때 모든 테스트가 통과하는 topCoder 문제를 해결했습니다. 그럼에도 불구하고 전체 테스트 클래스를 실행할 때 일부는 실패합니다. 이 행동의 이유를 식별하는 데 도움을 주시겠습니까? 내 수업과 테스트는 다음과 같습니다.

package com.topcoder.div2.stage1;
import java.util.Arrays;
public class GameOfStones {
    private int iterations= 0;
    public int count(int[] stones){
        int result= checkEquality(stones);
        return result;
    }
    private int checkEquality(int[] stones){
        int count= 0;
        int sum= 0;
        for(int k= 0; k< stones.length;k++){
            sum += stones[k];
        }
        if(stones.length > 0) {
            for (int i= 0; i < sum; i++) {
                Arrays.sort(stones);
                if(stones[stones.length-1] != 3) {
                    int j= 0;
                    while (j < stones.length -1) {
                        if (stones[j]== stones[j + 1]) {
                            count++;
                        }
                        j++;
                    }
                    if (count== stones.length -1) {
                        return iterations;
                    }
                    stones[0]= stones[0] + 2;
                    stones[stones.length -1]= stones[stones.length -1] -2;
                    iterations++;
                    count= 0;
                }
            }
        }
        return -1;
    }
}

테스트:

package com.topcoder.div2.stage1;
import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;
public class GameOfStonesTest {
    private GameOfStones gameOfStones= new GameOfStones();
    @Test
    public void test1() {
        int expected= 0;
        int[] given= {17};
        int actual= gameOfStones.count(given);
        assertEquals(expected, actual);
    }
    @Test
    public void test2() {
        int expected= 3;
        int[] given={7, 15, 9, 5};
        int actual= gameOfStones.count(given);
        assertEquals(actual, expected);
    }
    @Test
    public void test3() {
        int expected= -1;
        int[] given={2, 8, 4};
        int actual= gameOfStones.count(given);
        assertEquals(actual, expected);
    }
    @Test
    public void test4() {
        int expected= -1;
        int[] given={10, 15, 20, 12, 1, 20};
        int actual= gameOfStones.count(given);
        assertEquals(actual, expected);
    }
    @Test
    public void test5(){
        int expected= 277;
        int[] given={17, 1, 27, 29, 13, 1, 27, 3, 19, 3, 25, 1, 11, 9, 7, 17, 31, 25, 5, 11, 31, 9,
                15, 3, 3, 3, 11, 11, 1, 41, 5, 95, 7, 3, 41, 31, 7, 13, 15, 5, 17, 3, 9, 3, 11,
                27, 1, 23, 15, 5, 43, 11, 17, 7, 1, 3, 13, 69, 3, 43, 21, 1, 25, 1, 3, 11, 5, 43,
                13, 7, 15, 1, 1, 55, 37, 9, 5, 7, 21, 3, 23, 15, 1, 9, 3, 35, 13, 17, 7, 17, 27, 5,
                9, 19, 13, 1, 1, 1, 29};
        int actual= gameOfStones.count(given);
        assertEquals(actual, expected);
    }
    @Test
     public void test6(){
        int expected= 539;
        int[] given={1, 29, 11, 35, 57, 15, 85, 19, 5, 47, 53, 5, 63, 19, 13, 63, 27, 43, 53, 75, 67, 93, 33, 31, 47, 3,
                63, 17, 11, 53, 35, 23, 17, 45, 31, 19, 63, 75, 5, 3, 49, 19, 11, 89, 21, 69,
                71, 5, 45, 81, 31, 13, 11, 19, 7, 99, 33, 63, 19, 57, 73, 29, 35, 9, 47,
                1, 17, 7, 13, 31, 5, 85, 95, 23, 45, 65, 63, 41, 81, 33, 45, 1, 15,
                45, 19, 87, 51, 7, 13, 39, 1, 59, 29, 35, 1, 43};
        int actual= gameOfStones.count(given);
        assertEquals(actual, expected);
    }
    @Test
    public void test7() {
        int expected= 0;
        int[] given={100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
                100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
                100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
                100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
                100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
                100, 100};
        int actual= gameOfStones.count(given);
        assertEquals(actual, expected);
    }
    @Test
    public void test8() {
        int expected= 11;
        int[] given={3, 5, 21, 31};
        int actual= gameOfStones.count(given);
        assertEquals(actual, expected);
    }
    @Test
    public void test9() {
        int expected= 13;
        int[] given={44, 6, 46};
        int actual= gameOfStones.count(given);
        assertEquals(actual, expected);
    }
}

추신 솔루션 개선에 대한 제안 사항을 알고 계시다면 답변에 포함해 주시기 바랍니다.

모든 테스트에 대해 하나의 GameOfStones 인스턴스를 사용하고 있으므로 현재 테스트에 대한 마지막 테스트의 반복 값을 재사용하고 있습니다. count 메서드에서 반복을 재설정하거나 @BarrySW19가 제안한 대로 수행합니다.

Tom2022-01-14 14:36:14
  • 답변 # 1

    저도 비슷한 문제에 직면했고 추가 Mockito 주석이나 Mockito.reset을 사용하지 않고 빠르게 해결할 수 있었습니다. 여기있어 - https://anita15.medium.com/mockito-you-made-me-crazy-13be8fcddcfc

  • 답변 # 2

    Junit 5용 @BeforeEach도 시도할 수 있습니다.

    @BeforeEach
    public void setup() {
      //Some code here
    }
    

  • 답변 # 3

    이 문제에 대한 제 경험을 추가하고 싶습니다.

    많은 디버깅을 수행한 후 DB에 가비지 데이터가 없고 기능에 영향을 주는 정적 변수도 없음을 확인할 수 있었습니다.

    또한 동일한 단위 테스트는 다른 환경에서 예상한 대로 개별적으로 모두 한 번에 통과합니다.

    Java 버전, MySQL 버전은 두 환경 모두에서 동일합니다. 유일한 차이점은 maven 버전이었습니다. 그래서 성공한 환경에서 사용한 것과 동일한 maven 버전을 구성했습니다.

    문제가 해결된 후.

  • 답변 # 4

    여러 테스트 케이스에서 테스트 중인 동일한 활동을 연달아 실행하고 동일한 IntentsTestRule 클래스 활동을 열기 때문에

    내 경우에는 activityTestRule 클래스 및 intentTestRule 클래스에서 finishActivity를 호출하여 문제를 해결할 수 있습니다.

    예:

    @After
    fun method() {
    mainActivityTestRule.finishActivity()
    mIntentsRule.finishActivity()
    }
    

  • 답변 # 5

    같은 문제가 있었습니다. 정적 필드인 로거를 조롱해야 했습니다. 따라서 클래스 로더는 테스트 중인 클래스를 처음 호출하는 동안 정적 필드의 단일 인스턴스만 생성하고 모든 추가 조롱 및 스터빙을 무시합니다. 별도로 실행하면 로거가 초기화되어 예상대로 로드되기 때문에 테스트가 녹색이었지만 다른 테스트 메서드와 함께 실행하면 모의 객체가 아닌 구체적인 객체로 초기화되었습니다. 해결 방법:

    • 만들다@BeforeClass정적 필드의 올바른 인스턴스가 처음에 생성되도록 하는 방법:

      @BeforeClass
        public static void setupBeforeClass() {
          PowerMockito.mockStatic(LoggerFactory.class);
          loggerMock= mock(Logger.class);
          when(LoggerFactory.getLogger(any(Class.class))).thenReturn(loggerMock);
       }
    

    • 모의에 대한 상호 작용은 다양한 테스트 실행에서 누적되고 있습니다. 따라서 각 테스트 메서드 실행에서 모의의 깨끗한 인스턴스를 얻으려면 모의를 재설정해야 합니다.@전에또는@후에방법:

        @Before
          public void setup() {
            //Reset interactions on the mocked logger
            Mockito.reset(loggerMock);
          }
    

    참고로 내 예에서는 PowerMock을 사용했기 때문에 해당 러너가 필요합니다.@RunWith(PowerMockRunner.class)그리고@PrepareForTest({LoggerFactory.class, MyClass.class)}진술.

  • 답변 # 6

    모든 테스트에서 테스트 중인 클래스의 단일 인스턴스를 공유하고 있습니다. 초기 할당을 제거하고 다음을 추가합니다.

    private GameOfStones gameOfStones; //Don't create an instance here
    @BeforeMethod
    public void setUp() {
        gameOfStones= new GameOfStones();
    }
    

    ... 각 테스트에 대해 새 인스턴스를 사용합니다. 각 테스트 후에 정리하는 것도 좋은 방법입니다.

    @AfterMethod
    public void tearDown() {
        gameOfStones= null;
    }
    

    여기에 제공된 예제에서 클래스 범위 변수를 수정하여 문제가 대신 메서드 범위로 지정되도록 하면 문제도 해결되지만 테스트 중인 소프트웨어가 더 복잡해지면 적절한 테스트 설정 및 해제를 시작하는 것이 좋습니다.

    물론 @Tom이 지적했듯이 '반복'이 GameOfThrones 개체를 공유할 수 있도록 하는 클래스 수준 변수가 아닌 메서드 로컬 변수인지 확인할 수도 있습니다. 하지만 적절한 테스트 설정 및 해제를 수행하는 것도 좋습니다. :)

    BarrySW192022-01-14 14:36:14

    주석을 @BeforeMethod 및 @AfterMethod로 변경할 수 있습니다. 해당하는 TestNG 주석이 있습니다. (@BeforeClass와 @BeforeTest도 있지만 작동 방식이 다릅니다)

    Tom2022-01-14 14:36:14

    JUnit을 사용하는 분들은 @Before와 @After를 사용해 보세요.

    Janac Meena2022-01-15 09:48:14

    이것은 조금 다르지만 내 대답이기도했습니다. ActivityScenarioRule을 사용하고 있었으므로 이제 @Before 메서드에서 acitivityRule을 할당합니다.

    mitch942022-01-15 12:26:38
  • 이전 php : AWS-SES 열기/클릭 추적
  • 다음 gitlab : 가라테에서 Geckodriver 세션 시간 초과