cocoapods-test-specs
$
npx mdskill add TheBushidoCollective/han/cocoapods-test-specsAutomate CocoaPods library validation with test specs.
- Ensures libraries pass lint checks before publishing.
- Integrates with pod lib lint and Quick/Nimble frameworks.
- Executes Ruby code to define test targets and dependencies.
- Generates runnable test suites for CI environments.
SKILL.md
.github/skills/cocoapods-test-specsView on GitHub ↗
---
name: cocoapods-test-specs
user-invocable: false
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
```ruby
Pod::Spec.new do |spec|
spec.name = 'MyLibrary'
spec.version = '1.0.0'
# Main library source
spec.source_files = 'Source/**/*.swift'
# Test spec
spec.test_spec 'Tests' do |test_spec|
test_spec.source_files = 'Tests/**/*.swift'
# Test dependencies
test_spec.dependency 'Quick', '~> 7.0'
test_spec.dependency 'Nimble', '~> 12.0'
end
end
```
## App Host Requirements
### Tests Without App Host
```ruby
spec.test_spec 'Tests' do |test_spec|
test_spec.source_files = 'Tests/**/*.swift'
# Unit tests that don't need app environment
test_spec.requires_app_host = false # Default
end
```
### Tests With App Host
```ruby
spec.test_spec 'UITests' do |test_spec|
test_spec.source_files = 'Tests/UITests/**/*.swift'
# Tests that need app environment (UIKit, storyboards, etc.)
test_spec.requires_app_host = true
test_spec.dependency 'MyLibrary'
end
```
## Multiple Test Specs
```ruby
Pod::Spec.new do |spec|
spec.name = 'MyLibrary'
# Unit tests (no app host)
spec.test_spec 'UnitTests' do |unit|
unit.source_files = 'Tests/Unit/**/*.swift'
unit.dependency 'Quick'
unit.dependency 'Nimble'
end
# Integration tests (with app host)
spec.test_spec 'IntegrationTests' do |integration|
integration.source_files = 'Tests/Integration/**/*.swift'
integration.requires_app_host = true
integration.dependency 'MyLibrary'
end
# UI tests (with app host)
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
```ruby
spec.test_spec 'Tests' do |test_spec|
# Shared test files
test_spec.source_files = 'Tests/Shared/**/*.swift'
# iOS-specific tests
test_spec.ios.source_files = 'Tests/iOS/**/*.swift'
test_spec.ios.frameworks = 'XCTest'
# macOS-specific tests
test_spec.osx.source_files = 'Tests/macOS/**/*.swift'
test_spec.osx.frameworks = 'XCTest'
end
```
## Test Dependencies
### Testing Frameworks
```ruby
spec.test_spec 'Tests' do |test_spec|
# Quick/Nimble (BDD style)
test_spec.dependency 'Quick', '~> 7.0'
test_spec.dependency 'Nimble', '~> 12.0'
# Or traditional XCTest (no additional dependencies)
test_spec.frameworks = 'XCTest'
end
```
### Mocking Frameworks
```ruby
spec.test_spec 'Tests' do |test_spec|
test_spec.source_files = 'Tests/**/*.swift'
# OCMock for Objective-C
test_spec.dependency 'OCMock', '~> 3.9'
# Cuckoo for Swift
test_spec.dependency 'Cuckoo', '~> 2.0'
# MockingKit for Swift
test_spec.dependency 'MockingKit', '~> 1.0'
end
```
## Test Resources
```ruby
spec.test_spec 'Tests' do |test_spec|
test_spec.source_files = 'Tests/**/*.swift'
# Test resources (JSON fixtures, images, etc.)
test_spec.resources = 'Tests/Fixtures/**/*'
# Or test resource bundle
test_spec.resource_bundles = {
'MyLibraryTests' => ['Tests/Fixtures/**/*']
}
end
```
## Scheme Configuration
```ruby
spec.test_spec 'Tests' do |test_spec|
test_spec.source_files = 'Tests/**/*.swift'
# Scheme name (optional - auto-generated if not specified)
test_spec.scheme = { :name => 'MyLibrary-Tests' }
# Code coverage
test_spec.scheme = {
:code_coverage => true
}
end
```
## Testing Subspecs
```ruby
Pod::Spec.new do |spec|
spec.name = 'MyLibrary'
# Core subspec
spec.subspec 'Core' do |core|
core.source_files = 'Source/Core/**/*.swift'
# Tests for Core subspec
core.test_spec 'Tests' do |test_spec|
test_spec.source_files = 'Tests/Core/**/*.swift'
test_spec.dependency 'Quick'
test_spec.dependency 'Nimble'
end
end
# Networking subspec
spec.subspec 'Networking' do |net|
net.source_files = 'Source/Networking/**/*.swift'
net.dependency 'MyLibrary/Core'
# Tests for Networking subspec
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
```ruby
spec.test_spec 'Tests' do |test_spec|
test_spec.source_files = 'Tests/**/*.swift'
test_spec.frameworks = 'XCTest'
# No additional dependencies needed
# Tests use import XCTest
end
```
### Quick/Nimble Pattern
```ruby
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'
# Tests use QuickSpec and expect()
end
```
### Network Mocking Pattern
```ruby
spec.test_spec 'NetworkTests' do |test_spec|
test_spec.source_files = 'Tests/Network/**/*.swift'
# Mock HTTP responses
test_spec.dependency 'OHHTTPStubs', '~> 9.0'
# Or URLProtocol-based mocking
test_spec.dependency 'Mocker', '~> 3.0'
end
```
### Snapshot Testing Pattern
```ruby
spec.test_spec 'SnapshotTests' do |test_spec|
test_spec.source_files = 'Tests/Snapshots/**/*.swift'
test_spec.requires_app_host = true
# Snapshot testing framework
test_spec.dependency 'SnapshotTesting', '~> 1.15'
# Reference images
test_spec.resources = 'Tests/Snapshots/__Snapshots__/**/*'
end
```
## Running Tests
### During Lint Validation
```bash
# Tests run automatically
pod lib lint
# Skip tests (faster, but not recommended)
pod lib lint --skip-tests
# Verbose test output
pod lib lint --verbose
```
### Standalone Test Execution
```bash
# In Example app
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
```ruby
# Organize by test type
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
```ruby
spec.test_spec 'Tests' do |test_spec|
# Only test dependencies here
test_spec.dependency 'Quick'
test_spec.dependency 'Nimble'
# Main library dependencies go in main spec
# Not in test spec
end
```
## Anti-Patterns
### Don't
❌ Skip tests during validation
```bash
pod lib lint --skip-tests # Defeats purpose of test specs
```
❌ Mix test and production code
```ruby
spec.source_files = 'Source/**/*.swift', 'Tests/**/*.swift' # BAD
```
❌ Include test dependencies in main spec
```ruby
# In main spec
spec.dependency 'Quick' # Should be in test_spec only
```
❌ Use requires_app_host unnecessarily
```ruby
spec.test_spec 'Tests' do |test_spec|
# Pure unit tests don't need app host
test_spec.requires_app_host = true # Slower, unnecessary
end
```
### Do
✅ Run tests during every validation
```bash
pod lib lint # Includes tests by default
```
✅ Separate test and production code
```ruby
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
```ruby
spec.test_spec 'Tests' do |test_spec|
test_spec.dependency 'Quick' # Only for tests
end
```
✅ Use app host only when needed
```ruby
spec.test_spec 'Tests' do |test_spec|
# Only if tests need UIKit, storyboards, etc.
test_spec.requires_app_host = true
end
```
## Example: Complete Test Spec Setup
```ruby
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'
# Unit tests
spec.test_spec 'UnitTests' do |unit|
unit.source_files = 'Tests/Unit/**/*.swift'
unit.dependency 'Quick', '~> 7.0'
unit.dependency 'Nimble', '~> 12.0'
end
# Integration tests with app host
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
More from TheBushidoCollective/han
- absinthe-resolversUse when implementing GraphQL resolvers with Absinthe. Covers resolver patterns, dataloader integration, batching, and error handling.
- absinthe-schemaUse when designing GraphQL schemas with Absinthe. Covers type definitions, interfaces, unions, enums, and schema organization patterns.
- absinthe-subscriptionsUse when implementing real-time GraphQL subscriptions with Absinthe. Covers Phoenix channels, PubSub, and subscription patterns.
- act-docker-setupUse when configuring Docker environments for act, selecting runner images, managing container resources, or troubleshooting Docker-related issues with local GitHub Actions testing.
- act-local-testingUse when testing GitHub Actions workflows locally with act. Covers act CLI usage, Docker configuration, debugging workflows, and troubleshooting common issues when running workflows on your local machine.
- act-workflow-syntaxUse when creating or modifying GitHub Actions workflow files. Provides guidance on workflow syntax, triggers, jobs, steps, and expressions for creating valid GitHub Actions workflows that can be tested locally with act.
- ameba-configurationUse when configuring Ameba rules and settings for Crystal projects including .ameba.yml setup, rule management, severity levels, and code quality enforcement.
- ameba-custom-rulesUse when creating custom Ameba rules for Crystal code analysis including rule development, AST traversal, issue reporting, and rule testing.
- ameba-integrationUse when integrating Ameba into development workflows including CI/CD pipelines, pre-commit hooks, GitHub Actions, and automated code review processes.
- analyze-performanceAnalyze performance metrics and identify slow transactions in Sentry