Qt Test 모범 사례

버그 수정 및 새로운 기능에 대해 Qt 테스트를 추가하는 것이 좋습니다. 버그 수정을 시도하기 전에 버그 수정 전에는 실패하여 버그를 표시하고 수정 후에는 통과하는 회귀 테스트 (이상적으로는 자동)를 추가하세요. 새로운 기능을 개발하는 동안 테스트를 추가하여 의도한 대로 작동하는지 확인하세요.

일련의 코딩 표준을 준수하면 Qt 자동 테스트가 모든 환경에서 안정적으로 작동할 가능성이 높아집니다. 예를 들어, 일부 테스트는 디스크에서 데이터를 읽어야 합니다. 이 작업을 수행하는 방법에 대한 표준이 설정되어 있지 않으면 일부 테스트는 이식되지 않습니다. 예를 들어, 테스트 데이터 파일이 현재 작업 디렉터리에 있다고 가정하는 테스트는 인소스 빌드에서만 작동합니다. 섀도 빌드(소스 디렉터리 외부)에서는 테스트가 해당 데이터를 찾지 못합니다.

다음 섹션에는 Qt 테스트 작성에 대한 지침이 포함되어 있습니다:

일반 원칙

다음 섹션에서는 단위 테스트 작성에 대한 일반적인 지침을 제공합니다:

테스트 검증

수정 또는 새 기능과 함께 테스트를 작성하고 새 브랜치에 커밋하세요. 완료되면 작업의 기반이 되는 브랜치를 체크 아웃한 다음 이 브랜치에 새 테스트의 테스트 파일을 체크 아웃할 수 있습니다. 이렇게 하면 이전 브랜치에서 테스트가 실패했는지, 따라서 실제로 버그를 잡거나 새 기능을 테스트할 수 있는지 확인할 수 있습니다.

예를 들어 Git 버전 관리 시스템을 사용하는 경우 QDateTime 클래스의 버그를 수정하는 워크플로우는 다음과 같습니다:

  1. 수정 및 테스트를 위한 브랜치를 만듭니다: git checkout -b fix-branch 5.14
  2. 테스트를 작성하고 버그를 수정합니다.
  3. 수정 사항과 새 테스트를 모두 빌드하고 테스트하여 새 테스트가 수정 사항과 함께 통과하는지 확인합니다.
  4. 브랜치에 수정 및 테스트를 추가합니다: git add tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp src/corelib/time/qdatetime.cpp
  5. 브랜치에 수정 및 테스트를 커밋합니다: git commit -m 'Fix bug in QDateTime'
  6. 테스트가 실제로 수정이 필요한 것을 잡는지 확인하려면 자신의 브랜치를 기반으로 한 브랜치를 체크아웃하세요: git checkout 5.14
  7. 5.14 브랜치에 테스트 파일만 체크아웃합니다: git checkout fix-branch -- tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp

    이제 테스트만 수정 브랜치에 있습니다. 나머지 소스 트리는 여전히 5.14에 있습니다.

  8. 테스트를 빌드하고 실행하여 5.14에서 실패하는지, 따라서 실제로 버그를 잡는지 확인합니다.
  9. 이제 수정 브랜치로 돌아갈 수 있습니다: git checkout fix-branch
  10. 또는 5.14에서 작업 트리를 깨끗한 상태로 복원할 수 있습니다: git checkout HEAD -- tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp

변경 사항을 검토할 때 이 워크플로우를 조정하여 변경 사항이 실제로 수정하는 문제에 대한 테스트와 함께 제공되는지 확인할 수 있습니다.

테스트 함수에 설명이 포함된 이름 지정

테스트 케이스의 이름을 지정하는 것은 중요합니다. 테스트 이름은 테스트 실행에 대한 실패 보고서에 표시됩니다. 데이터 기반 테스트의 경우 데이터 행의 이름도 실패 보고서에 표시됩니다. 이름을 통해 보고서를 읽는 사람들은 무엇이 잘못되었는지를 먼저 알 수 있습니다.

테스트 함수 이름은 함수가 무엇을 테스트하려고 하는지 명확히 알 수 있어야 합니다. 버그 추적 식별자는 버그 추적기를 교체하면 더 이상 사용할 수 없으므로 단순히 버그 추적 식별자를 사용하지 마세요. 또한 일부 버그 추적기는 모든 사용자가 액세스하지 못할 수도 있습니다. 나중에 테스트 코드를 읽는 사람이 관심을 가질 만한 버그 보고서인 경우 테스트의 관련 부분과 함께 댓글로 언급할 수 있습니다.

마찬가지로 데이터 기반 테스트를 작성할 때는 테스트 케이스에 설명적인 이름을 지정하여 각 테스트가 기능의 어떤 측면에 초점을 맞추고 있는지를 나타냅니다. 단순히 테스트 케이스에 번호를 붙이거나 버그 추적 식별자를 사용하지 마세요. 테스트 결과를 읽는 사람은 숫자나 식별자가 무엇을 의미하는지 전혀 모를 것입니다. 필요한 경우 테스트 행에 버그 추적 식별자를 언급하는 주석을 추가할 수 있습니다. 테스트를 실행할 수 있는 명령줄 셸에 중요할 수 있는 문자와 문자를 띄어 쓰지 않는 것이 가장 좋습니다. 이렇게 하면 테스트 실행을 하나의 테스트 케이스로만 제한하는 등 테스트 프로그램에 대한 명령줄의 테스트 및 태그를 지정하기가 더 쉬워집니다.

독립된 테스트 함수 작성

테스트 프로그램 내에서 테스트 함수는 서로 독립적이어야 하며 이전에 실행된 테스트 함수에 의존해서는 안 됩니다. tst_foo testname 을 사용하여 테스트 함수를 자체적으로 실행하여 이를 확인할 수 있습니다.

테스트 중인 클래스의 인스턴스를 여러 테스트에서 재사용하지 마세요. 테스트 인스턴스(예: 위젯)는 테스트의 멤버 변수가 되어서는 안 되며, 테스트가 실패하더라도 테스트가 서로 간섭하지 않도록 스택에 인스턴스화하여 적절한 정리가 이루어지도록 하는 것이 바람직합니다.

전체 스택 테스트

API가 플러그형 또는 플랫폼별 백엔드로 구현되어 무거운 작업을 수행하는 경우 백엔드까지 코드 경로를 모두 커버하는 테스트를 작성해야 합니다. 모의 백엔드를 사용하여 상위 계층 API 부분을 테스트하는 것은 백엔드에서 API 계층의 오류를 분리하는 좋은 방법이지만 실제 데이터로 실제 구현을 실행하는 테스트와 보완적인 역할을 합니다.

테스트를 빠르게 완료하기

테스트가 불필요하게 반복되거나, 부적절하게 많은 양의 테스트 데이터를 사용하거나, 불필요한 유휴 시간을 유발하여 시간을 낭비해서는 안 됩니다.

특히 단위 테스트의 경우, 단위 테스트 실행 시간이 1초만 더 늘어나도 여러 대상에 걸친 브랜치에 대한 CI 테스트가 더 오래 걸립니다. 단위 테스트는 더 많은 양의 테스트 데이터와 더 긴 테스트 실행이 예상되는 부하 및 안정성 테스트와는 별개라는 점을 기억하세요.

일반적으로 동일한 테스트를 여러 번 실행하는 벤치마크 테스트는 별도의 tests/benchmarks 디렉터리에 위치해야 하며, 기능 단위 테스트와 혼용해서는 안 됩니다.

데이터 기반 테스트 사용

데이터 기반 테스트를 사용하면 이후 버그 보고서에서 발견된 경계 조건에 대한 새로운 테스트를 더 쉽게 추가할 수 있습니다.

테스트에서 여러 항목을 순차적으로 테스트하는 대신 데이터 중심 테스트를 사용하면 매우 유사한 코드의 반복을 줄이고 이전 케이스가 실패하더라도 이후 케이스를 테스트할 수 있습니다. 또한 각 데이터 샘플에 동일한 테스트가 적용되므로 체계적이고 균일한 테스트가 가능합니다.

테스트가 데이터 기반인 경우, 테스트의 명령줄에 테스트 함수 이름과 함께 데이터 태그를 function:tag 으로 지정하여 함수의 모든 테스트 케이스가 아닌 특정 테스트 케이스 하나에 대해서만 테스트를 실행할 수 있습니다. 이는 글로벌 데이터 태그 또는 로컬 태그에 사용할 수 있으며, 함수의 자체 데이터에서 행을 식별하는 데 사용할 수도 있고 function:global:local 과 같이 결합할 수도 있습니다.

커버리지 도구 사용

Coco 또는 gcov와 같은 커버리지 도구를 사용하면 테스트 중인 함수나 클래스에서 가능한 한 많은 문, 분기 및 조건을 포함하는 테스트를 작성하는 데 도움이 됩니다. 새 기능의 개발 주기에서 이 작업을 일찍 수행할수록 나중에 코드가 리팩터링될 때 회귀를 포착하기가 더 쉬워집니다.

테스트를 제외할 적절한 메커니즘 선택하기

적용 불가능한 테스트를 제외하기 위해 적절한 메커니즘을 선택하는 것이 중요합니다.

QSKIP()를 사용하여 전체 테스트 함수가 현재 테스트 환경에서 적용 불가능한 것으로 런타임에 발견되는 경우를 처리하세요. 테스트 함수의 일부만 건너뛰려면 조건문을 사용할 수 있으며, 선택적으로 qDebug() 호출을 통해 적용 불가능한 부분의 건너뛰기 이유를 보고할 수 있습니다.

결국 수정해야 하는 알려진 테스트 실패가 있는 경우 가능한 경우 나머지 테스트 실행을 지원하므로 QEXPECT_FAIL 을 사용하는 것이 좋습니다. 또한 문제가 여전히 존재하는지 확인하고 코드 관리자가 무의식적으로 문제를 수정한 경우 이를 알려주므로 Abort 플래그를 사용할 때도 이점을 얻을 수 있습니다.

데이터 기반 테스트의 테스트 함수 또는 데이터 행은 특정 플랫폼으로 제한하거나 #if 을 사용하여 활성화되는 특정 기능으로 제한할 수 있습니다. 그러나 #if 을 사용하여 테스트 함수를 건너뛰는 경우 moc 제한에 주의하세요. moc 전처리기는 컴파일러의 기능 감지에 자주 사용되는 컴파일러의 모든 builtin 매크로에 액세스할 수 없습니다. 따라서 moc 은 전처리기 조건에 대해 나머지 코드에서 보는 것과 다른 결과를 얻을 수 있습니다. 이로 인해 moc 이 실제 컴파일러가 건너뛴 테스트 슬롯에 대한 메타데이터를 생성하거나 실제로 클래스에 컴파일되는 테스트 슬롯에 대한 메타데이터를 생략할 수 있습니다. 첫 번째 경우 테스트는 구현되지 않은 슬롯을 실행하려고 시도합니다. 두 번째 경우에는 테스트가 테스트 슬롯을 실행해야 함에도 불구하고 테스트가 실행을 시도하지 않습니다.

특정 플랫폼에 전체 테스트 프로그램을 적용할 수 없거나 특정 기능이 활성화되어 있지 않은 경우 가장 좋은 방법은 상위 디렉터리의 빌드 구성을 사용하여 테스트를 빌드하지 않는 것입니다. 예를 들어 tests/auto/gui/someclass 테스트가 macOS에 유효하지 않은 경우 플랫폼 검사에서 tests/auto/gui/CMakeLists.txt 에 하위 디렉터리로 포함되도록 래핑합니다:

if(NOT APPLE)
    add_subdirectory(someclass)
endif

또는 qmake 을 사용하는 경우 tests/auto/gui.pro 에 다음 줄을 추가합니다:

mac*: SUBDIRS -= someclass

QSKIP로 테스트 건너뛰기를 참조하세요.

Q_ASSERT 피하기

Q_ASSERT 매크로는 어설션 조건이 false 일 때마다 프로그램이 중단되도록 하지만 소프트웨어가 디버그 모드로 빌드된 경우에만 해당됩니다. 릴리스 빌드와 디버그 및 릴리스 빌드 모두에서 Q_ASSERT 은 아무 작업도 수행하지 않습니다.

Q_ASSERT 는 디버그 빌드 여부에 따라 테스트가 다르게 동작하고, 테스트를 즉시 중단하여 나머지 모든 테스트 기능을 건너뛰고 불완전하거나 잘못된 테스트 결과를 반환하므로 피해야 합니다.

또한 테스트가 끝날 때 수행해야 하는 모든 정리 또는 정돈을 건너뛰기 때문에 작업 공간이 어수선한 상태로 남게 되어 추가 테스트에 문제를 일으킬 수 있습니다.

Q_ASSERT 대신 QCOMPARE() 또는 QVERIFY() 매크로 변형을 사용해야 합니다. 이 경우 현재 테스트가 실패를 보고하고 종료되지만 나머지 테스트 기능은 실행되고 전체 테스트 프로그램이 정상적으로 종료됩니다. QVERIFY2()는 테스트 로그에 설명적인 오류 메시지를 기록할 수도 있습니다.

신뢰할 수 있는 테스트 작성하기

다음 섹션에서는 신뢰할 수 있는 테스트를 작성하기 위한 지침을 제공합니다:

검증 단계에서 부작용 피하기

QCOMPARE(), QVERIFY() 등을 사용하여 자동 테스트에서 검증 단계를 수행할 때 부작용을 피해야 합니다. 확인 단계의 부작용은 테스트를 이해하기 어렵게 만들 수 있습니다. 또한 QTRY_VERIFY(), QTRY_COMPARE() 또는 QBENCHMARK()를 사용하도록 테스트를 변경하면 진단하기 어려운 방식으로 테스트가 쉽게 중단될 수 있습니다. 이러한 경우 전달된 표현식을 여러 번 실행하여 부작용을 반복할 수 있습니다.

부작용이 불가피한 경우 테스트가 실패하더라도 테스트 함수가 끝날 때 이전 상태가 복원되도록 하세요. 이를 위해서는 일반적으로 함수가 반환될 때 상태를 복원하는 RAII(자원 획득은 초기화) 클래스 또는 cleanup() 메서드를 사용해야 합니다. 테스트가 끝날 때 단순히 복원 코드를 넣지 마세요. 테스트의 일부가 실패하면 해당 코드는 건너뛰고 이전 상태가 복원되지 않습니다.

고정 시간 초과 방지

QTest::qWait()와 같이 일부 조건이 참이 될 때까지 기다리는 하드 코딩된 시간 초과를 사용하지 마세요. QSignalSpy 클래스, QTRY_VERIFY() 또는 QTRY_COMPARE() 매크로, 또는 QSignalSpy 클래스를 QTRY_ 매크로 변형과 함께 사용하는 것을 고려해 보세요.

qWait() 함수는 특정 작업을 수행하고 해당 작업으로 트리거된 비동기 동작이 완료될 때까지 일정 기간 동안 지연을 설정하는 데 사용할 수 있습니다. 예를 들어 위젯의 상태를 변경한 다음 위젯이 다시 그려질 때까지 기다리는 것입니다. 그러나 이러한 시간 초과로 인해 워크스테이션에서 작성된 테스트가 디바이스에서 실행될 때 예상 동작이 완료되는 데 시간이 오래 걸리는 경우가 종종 발생합니다. 가장 느린 테스트 플랫폼에서 고정 시간 제한을 필요한 것보다 몇 배 더 큰 값으로 늘리는 것은 모든 플랫폼, 특히 테이블 기반 테스트의 경우 테스트 실행 속도를 늦추므로 좋은 해결책이 아닙니다.

테스트 중인 코드가 비동기 동작이 완료될 때 Qt 신호를 발행하는 경우, QSignalSpy 클래스를 사용하여 테스트 함수에 이제 검증 단계를 수행할 수 있음을 알리는 것이 더 나은 접근 방식입니다.

Qt 신호가 없는 경우, 지정된 조건이 참이 되거나 최대 시간 초과에 도달할 때까지 주기적으로 테스트하는 QTRY_COMPARE()QTRY_VERIFY() 매크로를 사용합니다. 이러한 매크로는 테스트가 필요 이상으로 오래 걸리는 것을 방지하는 동시에 워크스테이션에서 테스트를 작성하고 나중에 임베디드 플랫폼에서 실행할 때 중단되는 것을 방지합니다.

Qt 신호가 없고 새 API 개발의 일부로 테스트를 작성하는 경우, 비동기 동작의 완료를 보고하는 신호를 추가하는 것이 API에 도움이 될 수 있는지 고려하세요.

타이밍에 의존하는 동작 주의하기

일부 테스트 전략은 특정 클래스의 타이밍 종속적 동작에 취약하여 특정 플랫폼에서만 실패하거나 일관된 결과를 반환하지 않는 테스트가 발생할 수 있습니다.

예를 들어 텍스트 입력 위젯은 깜박이는 커서가 있어 비트맵이 캡처될 때 커서 상태에 따라 캡처된 비트맵의 비교가 성공하거나 실패할 수 있는 경우가 많습니다. 이는 테스트를 실행하는 머신의 속도에 따라 달라질 수 있습니다.

타이머 이벤트에 따라 상태가 변경되는 클래스를 테스트할 때는 검증 단계를 수행할 때 타이머 기반 동작을 고려해야 합니다. 타이밍에 따라 달라지는 동작이 다양하기 때문에 이 테스트 문제에 대한 일반적인 해결책은 없습니다.

텍스트 입력 위젯의 경우 커서 깜박임 동작을 비활성화하거나(API에서 해당 기능을 제공하는 경우), 비트맵을 캡처하기 전에 커서가 알려진 상태가 될 때까지 기다리거나(예: API에서 적절한 신호를 구독하는 경우), 커서가 포함된 영역을 비트맵 비교에서 제외하는 등의 해결책이 있을 수 있습니다.

비트맵 캡처 및 비교 피하기

비트맵을 캡처하고 비교하여 테스트 결과를 확인하는 것이 필요한 경우도 있지만, 이는 매우 취약하고 노동 집약적일 수 있습니다.

예를 들어, 특정 위젯은 플랫폼마다 또는 위젯 스타일에 따라 모양이 다를 수 있으므로 참조 비트맵을 여러 번 생성한 다음 Qt의 지원 플랫폼 세트가 발전함에 따라 향후 유지 관리해야 할 수 있습니다. 따라서 비트맵에 영향을 미치는 변경을 수행하려면 지원되는 각 플랫폼에서 예상되는 비트맵을 다시 만들어야 하며, 이를 위해서는 각 플랫폼에 대한 액세스가 필요합니다.

비트맵 비교는 테스트 컴퓨터의 화면 해상도, 비트 심도, 활성 테마, 색 구성표, 위젯 스타일, 활성 로캘(통화 기호, 텍스트 방향 등), 글꼴 크기, 투명도 효과, 창 관리자 선택 등의 요인에 의해서도 영향을 받을 수 있습니다.

가능하면 비트맵을 캡처하고 비교하는 대신 객체 및 변수의 속성을 확인하는 등의 프로그래밍 방식을 사용하세요.

테스트 출력 개선

다음 섹션에서는 읽기 쉽고 유용한 테스트 출력을 생성하기 위한 지침을 제공합니다:

경고 테스트

소프트웨어를 빌드할 때와 마찬가지로, 테스트 출력이 경고로 어수선하면 버그 발생의 단서인 경고를 알아차리기 어렵습니다. 따라서 테스트 로그에서 경고 및 기타 불필요한 출력을 정기적으로 확인하고 원인을 조사하는 것이 현명합니다. 버그의 징후인 경우 경고를 통해 테스트 실패를 트리거할 수 있습니다.

테스트 중인 코드가 잘못된 사용에 대한 경고와 같은 메시지를 생성해야 하는 경우, 실제로 사용되었을 때 이러한 메시지가 생성되는지 테스트하는 것도 중요합니다. qWarning (), qDebug(), qInfo() 및 친구에서 생성되는 테스트 대상 코드에서 예상되는 메시지를 QTest::ignoreMessage()를 사용하여 테스트할 수 있습니다. 이렇게 하면 메시지가 생성되는지 확인하고 테스트 실행의 출력에서 필터링합니다. 메시지가 생성되지 않으면 테스트가 실패합니다.

Qt가 디버그 모드로 빌드된 경우에만 예상 메시지가 출력되는 경우 QLibraryInfo::isDebugBuild()를 사용하여 Qt 라이브러리가 디버그 모드로 빌드되었는지 여부를 확인합니다. #ifdef QT_DEBUG 을 사용하는 것은 테스트가 디버그 모드로 빌드되었는지 여부만 알려줄 뿐, Qt 라이브러리도 디버그 모드로 빌드되었다는 것을 보장하지 않으므로 충분하지 않습니다.

테스트가 QTest::failOnWarning()을 호출하여 qWarning()에 대한 호출을 트리거하지 않는지 확인할 수 있습니다(Qt 6.3 이후). 여기에는 테스트할 경고 메시지 또는 경고와 일치하는 QRegularExpression 가 필요하며, 일치하는 경고가 생성되면 보고되고 테스트가 실패하게 됩니다. 예를 들어, 경고를 전혀 생성하지 않아야 하는 테스트는 QTest::failOnWarning(QRegularExpression(u".*"_s)) 으로 설정하면 모든 경고와 일치할 수 있습니다.

환경 변수 QT_FATAL_WARNINGS 를 설정하여 경고를 치명적인 오류로 처리하도록 할 수도 있습니다. 자세한 내용은 qWarning()를 참조하세요. 이는 자동 테스트에만 해당되지 않습니다. 방대한 테스트 로그에서 경고를 놓칠 수 있는 경우 이 환경 변수를 설정하여 가끔 실행하면 발생하는 경고를 찾아서 제거하는 데 도움이 될 수 있습니다.

자동 테스트에서 디버그 메시지 인쇄 방지

자동 테스트는 처리되지 않은 경고 또는 디버그 메시지를 생성하지 않아야 합니다. 이렇게 하면 CI 게이트에서 새로운 경고 또는 디버그 메시지를 테스트 실패로 처리할 수 있습니다.

개발 중에 디버그 메시지를 추가하는 것은 괜찮지만 테스트가 체크인되기 전에 비활성화하거나 제거해야 합니다.

잘 구조화된 진단 코드 작성

테스트 실패 시 유용한 진단 출력은 주석 처리하거나 전처리기 지시어로 비활성화하거나 디버그 빌드에서만 활성화하지 말고 일반 테스트 출력의 일부로 포함시켜야 합니다. 지속적 통합 중에 테스트가 실패하는 경우 CI 로그에 관련 진단 출력이 모두 있으면 진단 코드를 활성화하고 다시 테스트하는 것보다 많은 시간을 절약할 수 있습니다. 특히 데스크톱에 설치되어 있지 않은 플랫폼에서 실패한 경우 더욱 그렇습니다.

테스트의 진단 메시지는 stdio.h 또는 iostream.h 출력 메커니즘이 아닌 qDebug()qWarning() 과 같은 Qt의 출력 메커니즘을 사용해야 합니다. 후자는 Qt의 메시지 처리를 우회하고 -silent 명령줄 옵션이 진단 메시지를 억제하지 못하도록 합니다. 이로 인해 중요한 실패 메시지가 대량의 디버깅 출력에 숨겨질 수 있습니다.

테스트 가능한 코드 작성하기

다음 섹션에서는 테스트하기 쉬운 코드를 작성하기 위한 지침을 제공합니다:

종속성 끊기

단위 테스트의 개념은 모든 클래스를 독립적으로 사용하는 것입니다. 많은 클래스가 다른 클래스를 인스턴스화하기 때문에 한 클래스를 따로 인스턴스화할 수 없습니다. 따라서 객체 생성과 객체 사용을 분리하는 종속성 주입이라는 기술을 사용해야 합니다. 팩토리는 객체 트리를 구축하는 역할을 합니다. 다른 객체는 추상 인터페이스를 통해 이러한 객체를 조작합니다.

이 기법은 데이터 기반 애플리케이션에 적합합니다. GUI 애플리케이션의 경우 객체가 자주 생성되고 소멸되기 때문에 이 접근 방식은 어려울 수 있습니다. 추상 인터페이스에 의존하는 클래스의 올바른 동작을 확인하기 위해 모킹을 사용할 수 있습니다. 예를 들어, 구글 테스트 모킹(gMock) 프레임워크를 참조하세요.

모든 클래스를 라이브러리로 컴파일

중소규모 프로젝트에서 빌드 스크립트는 일반적으로 모든 소스 파일을 나열한 다음 실행 파일을 한 번에 컴파일합니다. 즉, 테스트용 빌드 스크립트는 필요한 소스 파일을 다시 나열해야 합니다.

정적 라이브러리를 빌드할 때는 스크립트에 소스 파일과 헤더를 한 번만 나열하는 것이 더 쉽습니다. 그러면 main() 함수가 정적 라이브러리에 대해 링크되어 실행 파일을 빌드하고 테스트가 정적 라이브러리에 대해 링크됩니다.

여러 프로그램을 빌드하는 데 동일한 소스 파일을 사용하는 프로젝트의 경우 공유 클래스를 동적으로 링크된(또는 공유 객체) 라이브러리로 빌드하여 테스트 프로그램을 포함한 각 프로그램이 런타임에 로드할 수 있도록 하는 것이 더 적절할 수 있습니다. 다시 말하지만, 컴파일된 코드를 라이브러리에 보관하면 다양한 프로그램을 만들기 위해 어떤 컴포넌트를 결합할지 설명할 때 중복을 피하는 데 도움이 됩니다.

테스트 머신 설정하기

다음 섹션에서는 테스트 머신 설정으로 인해 발생하는 일반적인 문제에 대해 설명합니다:

이러한 모든 문제는 일반적으로 가상화를 신중하게 사용하면 해결할 수 있습니다.

화면 보호기

화면 보호기는 GUI 클래스에 대한 일부 테스트를 방해하여 신뢰할 수 없는 테스트 결과를 초래할 수 있습니다. 테스트 결과가 일관되고 신뢰할 수 있도록 화면 보호기를 비활성화해야 합니다.

시스템 대화 상자

운영 체제 또는 실행 중인 다른 애플리케이션에서 예기치 않게 표시되는 대화 상자는 자동 테스트에 관련된 위젯의 입력 포커스를 빼앗아 재현 불가능한 오류를 일으킬 수 있습니다.

일반적인 문제의 예로는 macOS의 온라인 업데이트 알림 대화 상자, 바이러스 스캐너의 잘못된 경보, 바이러스 서명 업데이트와 같은 예약된 작업, 워크스테이션으로 푸시된 소프트웨어 업데이트, 스택 위에 창을 띄우는 채팅 프로그램 등이 있습니다.

디스플레이 사용

일부 테스트는 테스트 머신의 디스플레이, 마우스, 키보드를 사용하므로 테스트 머신을 동시에 다른 용도로 사용하거나 여러 테스트를 동시에 실행하는 경우 실패할 수 있습니다.

CI 시스템은 이러한 문제를 방지하기 위해 전용 테스트 머신을 사용하지만 전용 테스트 머신이 없는 경우 두 번째 디스플레이에서 테스트를 실행하여 이 문제를 해결할 수 있습니다.

Unix에서는 Xephyr와 같은 중첩 또는 가상 X-서버에서 테스트를 실행할 수도 있습니다. 예를 들어 Xephyr에서 전체 테스트 세트를 실행하려면 다음 명령을 실행합니다:

Xephyr :1 -ac -screen 1920x1200 >/dev/null 2>&1 &
sleep 5
DISPLAY=:1 icewm >/dev/null 2>&1 &
cd tests/auto
make
DISPLAY=:1 make -k -j1 check

NVIDIA 바이너리 드라이버 사용자는 Xephyr가 GLX 확장을 제공하지 못할 수 있다는 점에 유의해야 합니다. Mesa libGL을 강제 실행하면 도움이 될 수 있습니다:

export LD_PRELOAD=/usr/lib/mesa-diverted/x86_64-linux-gnu/libGL.so.1

그러나 서로 다른 libGL 버전으로 Xephyr와 실제 X 서버에서 테스트를 실행하면 QML 디스크 캐시로 인해 테스트가 충돌할 수 있습니다. 이를 방지하려면 QML_DISABLE_DISK_CACHE=1 을 사용하십시오.

또는 오프스크린 플러그인을 사용하세요:

TESTARGS="-platform offscreen" make check -k -j1

창 관리자

Unix에서는 최소 두 개의 자동 테스트(tst_examplestst_gestures)를 실행하려면 창 관리자가 실행 중이어야 합니다. 따라서 중첩된 X-서버에서 이러한 테스트를 실행하는 경우 해당 X-서버에서 창 관리자도 실행해야 합니다.

디스플레이에 모든 창을 자동으로 배치하도록 창 관리자를 구성해야 합니다. 탭 창 관리자(twm)와 같은 일부 창 관리자에는 새 창을 수동으로 배치하는 모드가 있으므로 사용자 상호 작용 없이 테스트 스위트를 실행할 수 없습니다.

참고: 탭 창 관리자는 tst_gestures 자동 테스트가 구성을 잊어버리고 수동 창 배치로 되돌아가므로 전체 Qt 자동 테스트 제품군을 실행하는 데는 적합하지 않습니다.

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.