| name | cocoapods-test-specs |
| description | Use when adding automated tests to CocoaPods libraries using test specs. Covers test spec configuration, app host requirements, and testing patterns that integrate with pod lib lint validation. |
| allowed-tools | ["Read","Write","Edit","Bash","Grep","Glob"] |
CocoaPods - Test Specs
Integrate automated tests into your CocoaPods library that run during validation.
What Are Test Specs?
Test specs define test targets that CocoaPods builds and runs automatically during pod lib lint and pod spec lint validation.
Benefits
- Automatic Testing: Tests run during every lint validation
- Confidence: Validates library works as expected before publishing
- CI Integration: Consistent testing across all environments
- Documentation: Tests serve as usage examples
Basic Test Spec
Pod::Spec.new do |spec|
spec.name = 'MyLibrary'
spec.version = '1.0.0'
spec.source_files = 'Source/**/*.swift'
spec.test_spec 'Tests' do |test_spec|
test_spec.source_files = 'Tests/**/*.swift'
test_spec.dependency 'Quick', '~> 7.0'
test_spec.dependency 'Nimble', '~> 12.0'
end
end
App Host Requirements
Tests Without App Host
spec.test_spec 'Tests' do |test_spec|
test_spec.source_files = 'Tests/**/*.swift'
test_spec.requires_app_host = false
end
Tests With App Host
spec.test_spec 'UITests' do |test_spec|
test_spec.source_files = 'Tests/UITests/**/*.swift'
test_spec.requires_app_host = true
test_spec.dependency 'MyLibrary'
end
Multiple Test Specs
Pod::Spec.new do |spec|
spec.name = 'MyLibrary'
spec.test_spec 'UnitTests' do |unit|
unit.source_files = 'Tests/Unit/**/*.swift'
unit.dependency 'Quick'
unit.dependency 'Nimble'
end
spec.test_spec 'IntegrationTests' do |integration|
integration.source_files = 'Tests/Integration/**/*.swift'
integration.requires_app_host = true
integration.dependency 'MyLibrary'
end
spec.test_spec 'UITests' do |ui|
ui.source_files = 'Tests/UI/**/*.swift'
ui.requires_app_host = true
ui.dependency 'MyLibrary'
ui.ios.frameworks = 'XCTest'
end
end
Platform-Specific Test Specs
spec.test_spec 'Tests' do |test_spec|
test_spec.source_files = 'Tests/Shared/**/*.swift'
test_spec.ios.source_files = 'Tests/iOS/**/*.swift'
test_spec.ios.frameworks = 'XCTest'
test_spec.osx.source_files = 'Tests/macOS/**/*.swift'
test_spec.osx.frameworks = 'XCTest'
end
Test Dependencies
Testing Frameworks
spec.test_spec 'Tests' do |test_spec|
test_spec.dependency 'Quick', '~> 7.0'
test_spec.dependency 'Nimble', '~> 12.0'
test_spec.frameworks = 'XCTest'
end
Mocking Frameworks
spec.test_spec 'Tests' do |test_spec|
test_spec.source_files = 'Tests/**/*.swift'
test_spec.dependency 'OCMock', '~> 3.9'
test_spec.dependency 'Cuckoo', '~> 2.0'
test_spec.dependency 'MockingKit', '~> 1.0'
end
Test Resources
spec.test_spec 'Tests' do |test_spec|
test_spec.source_files = 'Tests/**/*.swift'
test_spec.resources = 'Tests/Fixtures/**/*'
test_spec.resource_bundles = {
'MyLibraryTests' => ['Tests/Fixtures/**/*']
}
end
Scheme Configuration
spec.test_spec 'Tests' do |test_spec|
test_spec.source_files = 'Tests/**/*.swift'
test_spec.scheme = { :name => 'MyLibrary-Tests' }
test_spec.scheme = {
:code_coverage => true
}
end
Testing Subspecs
Pod::Spec.new do |spec|
spec.name = 'MyLibrary'
spec.subspec 'Core' do |core|
core.source_files = 'Source/Core/**/*.swift'
core.test_spec 'Tests' do |test_spec|
test_spec.source_files = 'Tests/Core/**/*.swift'
test_spec.dependency 'Quick'
test_spec.dependency 'Nimble'
end
end
spec.subspec 'Networking' do |net|
net.source_files = 'Source/Networking/**/*.swift'
net.dependency 'MyLibrary/Core'
net.test_spec 'Tests' do |test_spec|
test_spec.source_files = 'Tests/Networking/**/*.swift'
test_spec.dependency 'OHHTTPStubs', '~> 9.0'
end
end
end
Common Testing Patterns
XCTest Pattern
spec.test_spec 'Tests' do |test_spec|
test_spec.source_files = 'Tests/**/*.swift'
test_spec.frameworks = 'XCTest'
end
Quick/Nimble Pattern
spec.test_spec 'Tests' do |test_spec|
test_spec.source_files = 'Tests/**/*.swift'
test_spec.dependency 'Quick', '~> 7.0'
test_spec.dependency 'Nimble', '~> 12.0'
end
Network Mocking Pattern
spec.test_spec 'NetworkTests' do |test_spec|
test_spec.source_files = 'Tests/Network/**/*.swift'
test_spec.dependency 'OHHTTPStubs', '~> 9.0'
test_spec.dependency 'Mocker', '~> 3.0'
end
Snapshot Testing Pattern
spec.test_spec 'SnapshotTests' do |test_spec|
test_spec.source_files = 'Tests/Snapshots/**/*.swift'
test_spec.requires_app_host = true
test_spec.dependency 'SnapshotTesting', '~> 1.15'
test_spec.resources = 'Tests/Snapshots/__Snapshots__/**/*'
end
Running Tests
During Lint Validation
pod lib lint
pod lib lint --skip-tests
pod lib lint --verbose
Standalone Test Execution
cd Example
pod install
xcodebuild test -workspace MyLibrary.xcworkspace -scheme MyLibrary-Tests
Best Practices
Directory Structure
MyLibrary/
├── MyLibrary.podspec
├── Source/
│ └── MyLibrary/
├── Tests/
│ ├── Unit/ # Unit tests
│ ├── Integration/ # Integration tests
│ ├── UI/ # UI tests
│ └── Fixtures/ # Test data
└── Example/
└── MyLibraryExample.xcodeproj
Test Organization
spec.test_spec 'UnitTests' do |unit|
unit.source_files = 'Tests/Unit/**/*.swift'
unit.dependency 'Quick'
unit.dependency 'Nimble'
end
spec.test_spec 'IntegrationTests' do |integration|
integration.source_files = 'Tests/Integration/**/*.swift'
integration.requires_app_host = true
end
Dependency Management
spec.test_spec 'Tests' do |test_spec|
test_spec.dependency 'Quick'
test_spec.dependency 'Nimble'
end
Anti-Patterns
Don't
❌ Skip tests during validation
pod lib lint --skip-tests
❌ Mix test and production code
spec.source_files = 'Source/**/*.swift', 'Tests/**/*.swift'
❌ Include test dependencies in main spec
spec.dependency 'Quick'
❌ Use requires_app_host unnecessarily
spec.test_spec 'Tests' do |test_spec|
test_spec.requires_app_host = true
end
Do
✅ Run tests during every validation
pod lib lint
✅ Separate test and production code
spec.source_files = 'Source/**/*.swift'
spec.test_spec 'Tests' do |test_spec|
test_spec.source_files = 'Tests/**/*.swift'
end
✅ Keep test dependencies in test spec
spec.test_spec 'Tests' do |test_spec|
test_spec.dependency 'Quick'
end
✅ Use app host only when needed
spec.test_spec 'Tests' do |test_spec|
test_spec.requires_app_host = true
end
Example: Complete Test Spec Setup
Pod::Spec.new do |spec|
spec.name = 'MyAwesomeLibrary'
spec.version = '1.0.0'
spec.summary = 'An awesome library'
spec.homepage = 'https://github.com/username/MyAwesomeLibrary'
spec.license = { :type => 'MIT', :file => 'LICENSE' }
spec.authors = { 'Your Name' => 'email@example.com' }
spec.source = { :git => 'https://github.com/username/MyAwesomeLibrary.git', :tag => spec.version.to_s }
spec.ios.deployment_target = '13.0'
spec.swift_versions = ['5.7', '5.8', '5.9']
spec.source_files = 'Source/**/*.swift'
spec.test_spec 'UnitTests' do |unit|
unit.source_files = 'Tests/Unit/**/*.swift'
unit.dependency 'Quick', '~> 7.0'
unit.dependency 'Nimble', '~> 12.0'
end
spec.test_spec 'IntegrationTests' do |integration|
integration.source_files = 'Tests/Integration/**/*.swift'
integration.requires_app_host = true
integration.dependency 'OHHTTPStubs', '~> 9.0'
end
end
Related Skills
- cocoapods-podspec-fundamentals
- cocoapods-subspecs-organization
- cocoapods-publishing-workflow