스트리밍은 대부분의 브라우저와
Developer 앱에서 사용할 수 있습니다.
-
Xcode Cloud를 위한 빠르고 안정적인 테스트 작성
Apple의 지속적 통합 및 제공 서비스인 Xcode Cloud를 위한 효과적인 테스팅 계획을 수립하는 방법을 알아보세요. 테스트가 어떤 점에서 코드가 정상 작동하는지 지속적으로 확인하기 위한 필수 도구인지 보여드리겠습니다. Xcode Cloud를 위한 빠르고 안정적이며 효율적인 테스트를 작성하여 부적절한 오류를 방지하고 코드 변경 사항을 빠르게 확인하는 방법을 알아보세요.
리소스
관련 비디오
WWDC23
WWDC22
WWDC21
- Customize your advanced Xcode Cloud workflows
- Diagnose unreliable code with test repetitions
- Embrace Expected Failures in XCTest
- Meet Xcode Cloud
WWDC20
WWDC19
WWDC18
-
다운로드
안녕하세요 'Xcode Cloud를 위한 빠르고 안정적인 테스트 작성' 세션에 오신 것을 환영합니다 제 이름은 Suzy이고 XCTest에서 일하고 있습니다 이 세션에서는 Xcode Cloud 테스트를 시작하는 가장 효과적인 방법에 대해서 공유하겠습니다 저희는 Xcode Cloud를 개발자들의 강력한 도구로 설계했습니다 사실 Xcode 자체를 테스트하는데 사용하는데요, 아주 좋습니다 Xcode Cloud에서 제가 가장 좋아하는 기능 중 하나는 주어진 테스트 스위트를 상당히 확장할 수 있는 기능입니다
클라우드에서 실행될 대부분의 테스트를 구성하면 여러 대상에 테스트를 실행 가능한 실용적인 방법이 됩니다 다양한 운영 체제 버전을 실행하는 대상을 포함하여 iPhone, iPad, Apple Watch Apple TV, Mac과 같은 다양한 플랫폼을 활용하기 위해서요 또한 다양한 테스트 플랜 구성을 실행할 수 있도록 합니다 Address Sanitizer 및 Thread Sanitizer와 같은 런타임 분석 도구를 허용합니다 이러한 철저한 테스트 스위트를 통과하고 나면 코드를 수송할 준비가 되었다고 확신할 수 있습니다 테스트를 Xcode Cloud로 오프로딩하면 개발자 데스크탑 사이클 코드나 컴파일 및 테스트에 영향을 주지 않으면서 더 광범위한 테스트 세트를 실행할 수 있습니다 테스트 스위트가 확장되고 나면 신뢰할 수 없는 테스트 수가 증가할 가능성이 있습니다 관리할 수 없는 상황이 될 수도 있습니다 따라서 신뢰성을 보장하는 것이 필수적입니다 신뢰성 외에도, 이러한 방대한 양의 테스트는 효율적으로 실행되어야 합니다 지속적 통합 프로세스에 미치는 영향을 제한할 수 있도록 말이죠 먼저 신뢰성에 대해서 보겠습니다 Xcode Cloud에 대한 안정적인 테스트 작성 방법을 Food Truck(푸드트럭)을 사용하여 보여 드리겠습니다 푸드트럭은 탭, 쓸어넘기기 동작을 맛있는 도넛으로 변환합니다 Xcode Cloud에서 테스트 스위트를 실행함으로써 모든 Apple 플랫폼에서 제가 가장 좋아하는 초콜릿 스프링클 도넛의 주문을 지원하는지 검증할 수 있습니다 Xcode Cloud 워크플로에 대한 각각의 개선 사항을 식별해서 보여드리면서 시연하겠습니다 Xcode Cloud 워크플로에 대한 더 많은 내용은 'Xcode Cloud 알아보기' 강연을 시청하시기 바랍니다
보다 안정적인 테스트 작성을 위한 첫 단계는, 각 테스트의 setUp()과 tearDown()이 철저하게 이루어졌는지 확인하는 것입니다 Xcode Cloud로 실행되는 테스트는 새로운 시뮬레이터를 사용하기에 개발자의 원래 가정을 충족하지 않을 수 있습니다 그럼 이제 테스트 코드에서 가끔 볼 수 있는 여러 가지 기기 설정 가정들을 식별해 보겠습니다 어떤 특정 테스트들은 특정 날짜와 시간에 의존할 수도 있습니다 예시로, 서버가 다른 시간대에서 실행되고 있을 수 있습니다 테스트는 특정 시간대가 되는 것을 피해야 합니다 숫자 형식 및 언어 방향과 같은 로케일 기반 값은 예기치 않은 결과를 초래할 수 있습니다 시뮬레이터 로케일을 명시적으로 설정하여 이러한 문제를 피합니다 문제가 되는 또 다른 가정은 특정 기기 권한에 대한 의존입니다 인터넷 액세스와 같이 말이죠 단위 테스트에서 기기 권한을 모의해보고 UI 테스트에서 경고 핸들러를 사용하는 것이 좋습니다 마지막으로 일부 테스트는 미리 로드된 데이터에 의존합니다 빈 문서 디렉토리가 있을 것으로 예상하는 테스트의 경우와 같이요 시뮬레이터를 명시적으로 설정하는 것이 때로는 가장 쉬운 선택이지만 일반적으로는 테스트의 setUp 메서드 강화가 더 강력합니다 예를 들어 푸드트럭은 메뉴 파일에 의존합니다 setUp 함수에서 truck 객체를 인스턴스화하는 과정에서 도넛 메뉴 항목을 포함하는 모의 데이터 파일을 생성합니다 후속 테스트를 준비하기 위해 tearDown 메서드에 의존하기 보다 setUp 메서드에서 모든 상태에 대한 준비를 하는 것이 좋습니다 대부분의 경우 읽기 전용 파일은 저장소에 체크인 해놓고 나중에 테스트에서 액세스할 수 있습니다 하지만 이러한 파일을 구성해야 하는 경우 Xcode Cloud는 사용자 지정 빌드 스크립트 실행을 지원하기 때문에 여러 테스트의 액세스가 가능한 파일을 한번 생성할 수 있습니다 스크립트를 구성하는 방법에 대한 자세한 내용은 '사용자 지정 고급 Xcode Cloud 워크플로' 강연을 시청하세요
이제 제대로된 시뮬레이터 설정이 완료되었습니다 이제 전제 조건 미충족 테스트를 처리하는 방법에 대해 살펴봅시다 XCTSkip은 XCTest Runner가 현재 테스트 실행을 중지하고 건너뛴 것으로 표시하도록 지시하는 오류입니다 아직 미지원되는 OS 버전이나 기기 유형 우회에 사용될 수 있습니다 환경 변수를 설정하여 스테이징 또는 프로덕션 환경 관련 테스트를 건너뛰도록 XCTSkip을 활용할 수도 있습니다 환경 변수를 사용한 테스트 흐름 제어 방법에 대해서 살펴봅시다
환경 변수는 기기의 XCTest 테스트 러너 앱과 Xcode빌드를 실행하는 테스트 호스트 모두에 매개변수를 제공할 수 있습니다 Xcode Cloud에서 환경 변수에는 TEST_RUNNER_라는 접두사가 붙고 XCTest 테스트 러너에 전달됩니다 이 접두사는 환경 변수가 코드에서 사용 가능하게 되기 전에 제거됩니다 예를 들어, 테스트 코드에서 BASE_URL이라는 변수가 있을 때 이것은 TEST_RUNNER_BASE_URL이란 환경 변수로 전달됩니다 테스트 플랜은 테스트 코드와 동일한 형식을 요구합니다 즉, TEST_RUNNER_ 접두사를 붙이지 않습니다 환경 변수는 테스트 코드의 어느 곳에서나 참조될 수 있습니다 예를 들어 XCTSkip과 함께 사용하여 프로덕션 환경에 있을 때 실제로 도넛 주문을 건너뛰는데 사용할 수 있습니다 물론 배가 고프지 않다면 말이죠 명심해야 할 것은 여러 위치에서 환경 변수를 재정의할 경우 예시로 테스트 플랜, Xcode Cloud 사용자 인터페이스 모두에서 정의할 경우, 예기치 않은 결과가 발생할 수 있습니다 특별히 이 경우, Xcode Cloud의 환경 변수가 테스트 플랜에서 정의된 변수보다 우선합니다 테스트 코드 내에서의 환경 변수 참조에 대하여 Xcode Cloud 사용자 인터페이스에 해당 값을 지정하겠습니다
그러기 위해서, Cloud Reports로 이동하여 Food Truck을 컨트롤-클릭합니다
워크플로 내에서의 환경 변수를 편집하기 위해서 컨텍스트 메뉴에서 'Manage Workflows'를 선택합니다 우리는 특히 Integration 워크플로를 편집할 것입니다 따라서 이것을 더블 클릭합니다 이제 사이드바에서 'Environment'를 선택하고 시트 중간 "Environment Variables" 아래에서 변수의 이름과 값을 추가해줄 수 있습니다
Xcode Cloud 워크플로에서 환경 변수를 설정하는 대신 테스트 플랜에서 설정할 수 있습니다 이 예시에서는 아직 테스트 플랜이 없습니다 테스트 플랜을 활성화하려면 Scheme 편집기를 열고 사이드바에서 'Test'를 선택한 뒤 'Convert to Use Test Plans'를 클릭합니다
이제 테스트 플랜이 생겼습니다 'Food Truck' 이라고 하겠습니다 환경 변수를 추가하려면 테스트 플랜을 클릭하여 편집기를 열어야 합니다
'Tests' 나 'Configurations'를 상단에서 선택할 수 있습니다 'Configurations'를 선택하겠습니다 이제 'Arguments' 섹션에서 'Environment Variables'를 클릭하여 변수를 추가합니다 그럼 변수 명과 값을 입력가능한 팝업 창이 나타납니다
이제 프로덕션 환경에서는 테스트를 건너뛰게 됩니다 테스트 건너뛰기에 대해 자세히 알아보려면 'XCTSkip 테스트 건너뛰기' 강연을 시청하세요
XCTSkip 제어를 위해 환경 변수를 활용하는 방법을 다루었으므로 예상 시간 초과에 대해 이야기해 보겠습니다 예기치 않은 시간 초과로 테스트가 실패할 수 있습니다 이것은 서버가 느려서 발생한 결과일 수도 있고 매우 불안한 사용자 인터페이스 테스트의 결과일 수도 있습니다 이들 중 하나를 해결하는 한 가지 방법은 XCTestExpectation의 timeout을 늘려 상호 작용 완료를 위해 충분한 시간을 갖도록 하는 것입니다 이 예시에서, 우리는 OrderDonut의 timeout을 5초에서 10초로 늘려서 서버가 응답할 시간을 더 주었습니다 그러나 일반적으로 앱과 테스트 코드의 시간 초과 처리를 모두 async/await으로 교체하는 것이 좋습니다 이 접근 방식을 사용하면 시간 초과 없이 대기 호출이 완료될 때까지 테스트를 일시 중지할 수 있습니다
시간 종속 테스트를 해결했으므로 이제 테스트 스위트 내에서의 테스트 실패에 대한 처리를 봅시다 예를 들면 유지 관리를 위해 다운된 스테이징 환경 내의 서비스에 의존하는 테스트가 있습니다 테스트 비활성화 및 건너뛰기 대신 XCTExpectFailure를 사용합니다 XCTExpectFailure를 사용하면 테스트는 정상적으로 실행되고 결과는 다음과 같이 변환됩니다 한 테스트에서의 한 실패는 이제 예상된 실패로 보고되고 테스트 스위트 내의, 이 실패한 테스트는 통과로 보고됩니다 이 접근법은 예상된 실패를 통해 생성되는 노이즈를 제거합니다
예를 들어 testOrderDonut 함수가 실패하고 있고 도넛 주문을 제공하는 서비스가 현재 점검 중인 것을 알고 있다면 여기에 XCTExpectFailure 호출을 추가해줄 수 있습니다 XCTExpectFailure에 대해 자세히 알아보려면 'XCTest에서 예상되는 실패 수용' 강연을 시청하세요
이제 예상되는 실패 선언을 했으므로 테스트 반복을 활용하여 코드를 입증하고 신뢰할 수 없는 코드 진단을 해보겠습니다 테스트 반복은 같은 테스트를 여러 번 실행하는 도구입니다 다음을 기다리면서 말이죠 첫 번째 실패, 첫 번째 성공 또는 통계 결과를 기다립니다 예를 들어, 우리 데스크에서는 새로운 코드와 테스트 케이스를 여러 번 반복적으로 실행합니다 초기 앱을 확인하고 코드 안정성을 테스트하기 위해서요 코드를 체크인 하기 이전에 말이죠 testOrderDonut의 성공률이 80%에 불과하다는 것을 감지했습니다 이런! 오류가 존재함을 알고 있으므로 실패할 때까지 반복하는 모드를 사용하여 로컬에서 버그를 진단합니다 테스트 반복을 활용하는 또 다른 방법입니다 신뢰할 수 없는 외부 서비스에 의존하는 테스트의 경우 실패 시 재시도 반복 모드를 활용하여 테스트가 성공할 수 있는지를 확인할 수 있습니다 테스트 재시도는 강력한 접근 방식 일 수 있지만 가능하면 외부 모의 서비스를 대신 사용하는 것이 좋습니다 모의 서비스의 장점엔 결정론적 안정성과 속도가 있습니다 종속성 모의 방법에 대해 알아보려면 '테스팅 팁 및 요령' 강연을 시청하세요 테스트 반복을 활성화하는 방법을 살펴보겠습니다
테스트 플랜에서 테스트 반복을 활성화하려면 테스트 플랜 편집기로 돌아가서 'Configurations'를 선택합니다
그 다음 'Test Execution' 섹션 아래 테스트 반복 모드를 선택가능한 팝업 창이 있습니다
이 경우 'Retry on Failure'을 선택하겠습니다 신뢰할 수 없는 외부 서비스를 해결하는데 주로 사용됩니다 이제 테스트 반복 모드가 활성화되었습니다 테스트 반복 활용에 대한 자세한 내용은 '테스트 반복으로 신뢰할 수 없는 코드 진단' 강연을 시청하세요 지금까지 테스트 신뢰성 향상에 사용할 수 있는 다양한 도구를 살펴보았습니다 품질 테스트 작성에 대한 자세한 내용은 '실패할 테스트 작성' 강연을 시청하세요 이제 테스트를 신뢰할 수 있으므로 빠르게 실행하도록 해보겠습니다 보다 빠른 결과를 얻기 위한 여러 설정 옵션이 있습니다 테스트 스위트 소요 시간 단축을 위해 할 수 있는 일을 해봅시다
성능 향상을 위해 사용하는 한 가지 기법은 테스트들을 여러 테스트 플랜으로 분할하는 것입니다 때로는 두 개면 충분합니다 pull 요청에 대한 각 오픈되거나 업데이트된 부분의 일부를 검증하기 위하여 축소된 테스트를 식별할 수 있습니다
예를 들어, 단일 플랫폼에 대한 사용자 인터페이스 테스트의 주요 부분 집합과 함께 단위 테스트를 진행할 수 있습니다
지원되는 모든 플랫폼에서 전체 테스트를 계속 진행할 수 있습니다 이제는 백그라운드에서 진행되며 pull 요청을 차단하지 않습니다
이 접근 방식은 지속적 통합 프로세스를 적시에 유지하면서 테스트와 새로운 플랫폼을 추가할 수 있도록 해줍니다
선별된 테스트 세트를 실행하기 위해 워크플로를 설정하겠습니다 예시에서는 이미 새 테스트 플랜 'Pull Requests'를 생성했습니다 그리고 테스트 플랜 편집기에서 열었습니다 'Tests'나 'Configurations'를 상단에서 선택할 수 있습니다 'Tests'를 선택하겠습니다
여기에 pull 요청에 대해 확인할 테스트 부분 집합을 선택했습니다 'Pull Requests' 테스트 플랜 실행 용 워크플로 설정을 위해 Xcode Cloud의 Manage Workflows로 돌아가겠습니다 테스트 건너뛰기를 위해 환경 변수를 추가했을 때와 같습니다 'Add' 버튼을 클릭해서 새 워크플로를 생성합니다 'Manage Workflows' 시트의 좌측 하단에 있습니다 단순화를 위해 워크플로 이름도 'Pull Requests'로 지정하겠습니다 그리고 시작 조건을 선택합니다 이 워크플로가 테스트에 실패한 모든 체크인을 방지하길 바랍니다 사이드바에서 'Start Conditions' 우측에 있는 'Add' 버튼을 클릭하겠습니다
시작 조건 옵션을 보여주는 메뉴가 하나 나타납니다 이 경우 'Pull Request Changes'를 선택해주겠습니다
이제 pull 요청 시작 조건이 있습니다 테스트를 실행하려면 먼저 Food Truck 앱을 빌드해야 합니다 이렇게 하려면 빌드 액션을 추가해야 합니다 다시 사이드바의 'Start Conditions' 아래 액션을 하나 추가합시다 'Actions' 옆에 있는 'Add' 버튼을 클릭하고 컨텍스트 메뉴에서 'Build'를 선택합니다
이제 앱을 빌드하는 액션이 생겼으니 테스트를 실행할 다른 액션을 하나 더 추가하겠습니다 다시 액션 추가 버튼을 클릭하지만 이번에는 'Test'를 선택합니다
좋습니다, 이제 테스트 액션이 생겼습니다 이제 실행할 테스트 플랜을 선택합니다 시트 중간에 테스트에 대한 드롭다운이 있습니다 여기서 'Pull Requests' 테스트 플랜을 선택해줍니다
좋아요! 워크플로가 pull 요청 시 테스트 플랜의 실행 설정을 완료했습니다 완전한 테스트 스위트를 스케줄에 따라 실행할 두 번째 워크플로를 생성하려면 비슷한 일련의 단계를 따르면 됩니다 단, 이번에는 시작 조건을 'On a Schedule for a Branch'로 선택합니다 그리고 전체 테스트 플랜 스위트를 실행할 워크플로를 설정합니다 Xcode Cloud에 설정 완료된 워크플로가 있고 관련 테스트 플랜도 실행하고 있습니다 테스트 플랜을 자세히 알아보려면 'Xcode에서 테스팅'을 시청하세요
pull 요청과 스케줄된 워크플로 테스트 세트를 생성했습니다 속도 향상을 위해 또 가능한 것은 테스트 동시 실행입니다 기본적으로 Xcode Cloud는 플랫폼을 병렬로 테스트합니다 또한 Xcode가 대상 및 객체 클래스 수준에 대해 병렬로 테스트를 실행하도록 할 수 있습니다
Xcode에서 병렬 테스트 실행을 활성화 하려면 다시 테스트 플랜 편집기로 가서 'Tests'를 선택합니다
그런 다음 'Food Truck Tests' 테스트 번들의 우측에 있는 'Options' 버튼을 클릭합니다
'Execute in parallel'을 선택하면 가능한 경우 실행할 수 있습니다 서버에 사용 가능한 코어가 충분하면 여러 개의 대상 및 테스트 객체 클래스를 동시 실행할 수 있습니다 이 옵션을 활성화해서 테스트 스위트 처리시간 개선을 해봅시다
이제 테스트가 병렬로 실행 될 수 있도록 설정되었습니다 병렬 실행의 이점을 활용하려면 테스트가 독립적으로 실행되도록 설계해야 한다는 점에 주의하세요 바른 setUp과 tearDown은 믿음직한 테스트 케이스 동작에 필수입니다
테스트가 병렬로 실행된다면 런어웨이 테스트에 주의를 기울일 차례입니다 런어웨이 테스트란 적시에 끝나지 않는 테스트들을 말합니다 몇 가지 예에는 무한 루프 또는 실패한 서버에 대한 무기한 대기가 포함됩니다
테스트 플랜 실행 시간을 제한하여 그런 테스트들을 중지 가능합니다 실행 시간 제한은 테스트를 실행할 시간, 초의 수를 지정합니다 시간 초과 오류로 실패하기 전에요 이렇게 해서 테스트 스위트의 개별 테스트에서의 막힘을 방지합니다
이 경우, 어떤 이유로 다섯번째 테스트에서 막혔습니다 실행 시간 제한을 설정함으로써 이 런어웨이 테스트는 결국 중단되었고 실패로 표시되었습니다 그 후 XCTest Runner는 계속해서 다음 스위트 테스트를 실행합니다 테스트 플랜에 대한 실행 시간 제한을 설정해보겠습니다
실행 시간 제한을 설정하려면 테스트 플랜 편집기로 다시 이동해 'Configurations'을 선택합니다
'Test Execution' 카테고리 아래의 'Test Timeouts'를 활성화 합니다 대기 시간, 초 단위를 지정할 수 있습니다 기본값은 600초 입니다
최대 실행 시간 제한을 설정하면 더이상 단일 런어웨이 테스트가 테스트 워크플로를 방해하지 않습니다 예를 들어 익일 테스트 스위트는 이제 정시에 완료되어 완전한 세트의 유용한 결과를 제공할 수 있습니다 야호! 드디어 런어웨이 테스트를 중단할 수 있게 되었습니다 이제 다음 개선 사항으로 이동할 수 있습니다 기억하시겠지만, 테스트의 반복을 활용하여 외부 서비스에 의존하는 테스트의 신뢰성을 높일 수 있었습니다 우리는 테스트 플랜이 실패 시 재시도하도록 설정해주었고 충분한 반복값을 선택해주었습니다 하지만 반복은 테스트 스위트 실행 소요 시간 추가를 야기합니다
불필요한 반복은 낭비이기 때문에 테스트 반복 값을 더 낮게 최적화할 수 있습니다 또, Pull Requests 워크플로에서 문제되는 테스트를 완전히 제거하는 것을 고려할 수 있습니다 이 작업의 수행 방법을 살펴보겠습니다
테스트 플랜 편집기에서 테스트 반복 설정으로 돌아가 보겠습니다
앞서 테스트 반복 모드의 설정을 'Retry on Failure'로 했습니다 이제 'Maximum Test Repetitions' 값을 조정해줄 수 있습니다 예를 들어, 5%에 한번 실패하는 외부 서버에 의존하는 하나의 테스트에 대해 최대 10번의 시도를 허용하도록 선택해줄 수 있습니다 대부분의 경우는 첫 번째 시도에서 성공합니다 그러나 동일한 테스트에 관련 없는 버그가 있다면 매번 실패하게 되어 10번의 시도를 모두 사용하게 될 것입니다 어쩌면 3번의 시도가 더 나은 선택일 수 있습니다
성능 개선을 위해 재시도 횟수를 줄이는 것이 좋겠지만 이전에 일부 경우, 재시도 횟수를 늘려 신뢰성을 향상시키는 것을 권장했다는 점에 유의해야 합니다 따라서 이렇게 선택된 최소 값은 해당 테스트를 안정적으로 실행하기에 충분해야 합니다 이것으로 더 빠른 결과 도출을 위한 설정을 마무리하겠습니다 더 빠른 테스트 결과 도출 방법에 대해 자세히 알아보려면 '더 빠른 테스트 결과 도출' 강연을 시청하세요
요약하면 지금까지 Xcode Cloud로 테스팅을 시작하는 가장 효과적인 방법을 다뤘습니다 테스트를 신뢰할 수 있고 빠르도록 설정하는데 중점을 두었습니다 관련 없는 실패 방지 및 코드 변경 사항을 빨리 확인 가능하게 말이죠 감사드리며, 남은 WWDC도 즐겁게 보내시길 바랍니다
-
-
3:37 - setUp()
override func setUp() async throws { }
-
3:46 - setUp() example
var truck: Truck! override func setUp() async throws { let directoryURL = FileManager.default.temporaryDirectory let fileName = UUID().uuidString let fileURL = directoryURL.appendingPathComponent(fileName, isDirectory: false) let data = await mockDonutMenuData() try data.write(to: fileURL) truck = Truck(menuURL: fileURL) }
-
5:55 - Environment variable example
var truck: Truck! func testOrderDonut() throws { let host = ProcessInfo.processInfo.environment["BASE_URL"] let expectation = XCTestExpectation(description: "Order donut") truck.order(with: .sprinkles, host: host) { error, donut in XCTAssertTrue(donut.hasSprinkles) expectation.fulfill() } wait(for: [expectation], timeout: 5) }
-
6:00 - XCTSkip example
var truck: Truck! func testOrderDonut() throws { let host = ProcessInfo.processInfo.environment["BASE_URL"] try XCTSkipIf(host == "prod.example.com") let expectation = XCTestExpectation(description: "Order donut") truck.order(with: .sprinkles, host: host) { error, donut in XCTAssertTrue(donut.hasSprinkles) expectation.fulfill() } wait(for: [expectation], timeout: 5) }
-
8:18 - XCTSkip example
var truck: Truck! func testOrderDonut() throws { let host = ProcessInfo.processInfo.environment["BASE_URL"] try XCTSkipIf(host == "prod.example.com") let expectation = XCTestExpectation(description: "Order donut") truck.order(with: .sprinkles, host: host) { error, donut in XCTAssertTrue(donut.hasSprinkles) expectation.fulfill() } wait(for: [expectation], timeout: 5) }
-
8:48 - XCTestExpectation example
var truck: Truck! func testOrderDonut() throws { let host = ProcessInfo.processInfo.environment["BASE_URL"] try XCTSkipIf(host == "prod.example.com") let expectation = XCTestExpectation(description: "Order donut") truck.order(with: .sprinkles, host: host) { error, donut in XCTAssertTrue(donut.hasSprinkles) expectation.fulfill() } wait(for: [expectation], timeout: 5) }
-
8:59 - Increase XCTestExpectation example
var truck: Truck! func testOrderDonut() throws { let host = ProcessInfo.processInfo.environment["BASE_URL"] try XCTSkipIf(host == "prod.example.com") let expectation = XCTestExpectation(description: "Order donut") truck.order(with: .sprinkles, host: host) { error, donut in XCTAssertTrue(donut.hasSprinkles) expectation.fulfill() } wait(for: [expectation], timeout: 10) }
-
9:16 - Async/await example
var truck: Truck! func testOrderDonut() async throws { let host = ProcessInfo.processInfo.environment["BASE_URL"] try XCTSkipIf(host == "prod.example.com") let donut = try await truck.orderDonut(with: .sprinkles, host: host) XCTAssertTrue(donut.hasSprinkles) }
-
10:02 - XCTExpectFailure example
var truck: Truck! func testOrderDonut() async throws { let host = ProcessInfo.processInfo.environment["BASE_URL"] try XCTSkipIf(host == "prod.example.com") let donut = try await truck.orderDonut(with: .sprinkles, host: host) XCTAssertTrue(donut.hasSprinkles) }
-
10:06 - XCTExpectFailure example
var truck: Truck! func testOrderDonut() async throws { let host = ProcessInfo.processInfo.environment["BASE_URL"] try XCTSkipIf(host == "prod.example.com") XCTExpectFailure("<https://dev.myco.com/bug/98> Donut ordering service is down") let donut = try await truck.orderDonut(with: .sprinkles, host: host) XCTAssertTrue(donut.hasSprinkles) }
-
-
찾고 계신 콘텐츠가 있나요? 위에 주제를 입력하고 원하는 내용을 바로 검색해 보세요.
쿼리를 제출하는 중에 오류가 발생했습니다. 인터넷 연결을 확인하고 다시 시도해 주세요.