Convenient way to use collections of Sourcery stencils as an SPM plugins and Xcode plugins. This plugins provides simpler way to use sourcery binary with predefined templates without checking out whole sourcery repository. Learn more about it from the Sourcery here.
Add this configuration to your Package.swift:
dependencies: [
.package(url: "https://github.com/fenli/SourceryStencilPacks", from: "0.3.0"),
],Then add the plugins to your target:
.target(
name: "MyPackage",
plugins: [
// Regular target plugins
.plugin(name: "SourcePack", package: "SourceryStencilPacks")
]
)
.testTarget(
name: "MyPackageTests",
dependencies: ["MyPackage"],
plugins: [
// Test target plugins
.plugin(name: "TestPack", package: "SourceryStencilPacks")
]
),Integration into Xcode project:
- In Xcode root project, navigate to your targets list in side bar.
- Select target to integrate, eg: for TestPack plugins, select your
*Teststarget - Go to Build Phase -> Run Build Tool Plug-ins -> Add the plugin
Utility for generating boilerplate code like hashable, equatable, copyable, etc. Here are all the supported annotations:
| Annotation | Description |
|---|---|
Hashable |
Implements Hashable into classes, structs or enums |
Equatable |
Implements Equatable into classes, structs or enums |
Describable |
Implements CustomStringConvertible into classes, structs or enums |
Copyable |
Implements copy function into classes or structs |
DataRepresentable |
Combine all Hashable, Equatable, Describable, and Copyable |
// Generate hash, equals(==) and copy functions
// sourcery: Hashable, Equatable, Copyable
struct Product {
let name: String
let price: Double
let variants: [ProductVariant]
}
// Or simply use:
// sourcery: DataRepresentable
struct Product {
let name: String
let price: Double
let variants: [ProductVariant]
}Utility for generating test doubles like mocks, stubs, and fakes (by generating random object).
Use Mockable annotation to protocols to generate mocks/stubs and Randomizable to structs or enums to generate random fakes
// Generate ProductServiceMock() class
// sourcery: Mockable
class ProductService {
let repository: ProductRepository
init(repository: ProductRepository) {
self.repository = productRepository
}
func getProducts() async throws -> [Product] {
return try await repository.getAllProducts()
}
}
// Generate ProductRepositoryMock() class
// sourcery: Mockable
protocol ProductRepository {
func getAllProducts() async throws -> [Product]
}
// Generate Product.random() static function
// sourcery: Randomizable
struct Product {
let name: String // String.random() automatically generated
let price: Double // Double.random() automatically generated
let variants: [ProductVariant] // Need to annotate also on ProductVariant
}
// Generate ProductVariant.random() and [ProductVariant].random()
// sourcery: Randomizable=+array
struct ProductVariant: Equatable {
let id: Int
let name: String
}import Testing
@testable import SamplePackage
struct ProductServiceTests {
private var productRepositoryMock: ProductRepositoryMock!
private var service: ProductService!
init() {
productRepositoryMock = ProductRepositoryMock()
service = ProductService(productRepository: productRepositoryMock)
}
@Test
func testGetAllProductsSuccess() async throws {
// Generate fakes with random object
let fakeProducts = (0...5).map {_ in Product.random() }
// Use generated mocks for mocking/stubbing
productRepositoryMock.getAllProductsProductReturnValue = fakeProducts
// Action
let result = try await service.getProducts()
// Asserts
#expect(result == fakeProducts)
}
}Note
For primitive and standard types, random extension automatically generated. For example like String.random(), Int.random(), Double.random(), etc.
If plugins is applied in .testTarget, the Mocks and Random object only available from unit test. But, if you prefer to apply on regular .target please use config debug_only=true so it's not included in release binary.
For more sample usage, please see the SamplePackage.
Default plugin configuration should be suitable on most cases, but in case you need to customize it you can create .testpack.json inside your package directory (same level as Package.swift). All configuration keys here should be present otherwise it will use default value for all config.
{
"debug_only": true,
"random_std_lib": true,
"random_std_lib_protection": "fileprivate",
"imports": [],
"testable_imports": []
}| Key | Default Value | Description |
|---|---|---|
debug_only |
false |
Generate mocks/random for Debug build only. Default to false if applied on test target. If target is regular, then it's recommended to set as true |
random_std_lib |
true |
Generate std lib random extension |
random_std_lib_protection |
internal |
Protection level of std lib random extension. If target is regular, then it's recommended to set as fileprivate |
imports |
[] |
List of additional imports to generated sources |
testable_imports |
[] |
List of additional @testable imports to generated sources. Dependencies target is automatically added if target is test target. |
If you are using MockSwift, this plugin also provide autocreating the mocks using annotation // sourcery: MockSwift in your protocol. See sample here.
Are you using other testing tools to generate mock manually? you can suggest this plugin to integrate with that tools by submitting new issue.
SourceryStencilPacks is available under the Apache License Version 2.0. See LICENSE for more information.