I am porting legacy Objective-C
library to the Swift Package, which has Unit Tests written in Swift
. Previously, this library was written using standard approach: Framework target / Xcode project, so the test target could import internal headers (using bridging header). It seems as Swift Package manager does not offer anything like this, therefore testing internals looks problematic (without exposing them to the public). I tried to cheat it with exposing them using:
cSettings: [.headerSearchPath("../ObjcPackage/Source/Internal")]
But it does not work.
I am using swift-tools-version:5.3
Repo demonstrating the problem:
https://github.com/lukaszmargielewski/ObjcPackage
Some snippets:
1. Package definition:
// swift-tools-version:5.3
// Package.swift
import PackageDescription
let package = Package(
name: "ObjcPackage",
platforms: [
.iOS(.v10)
],
products: [
.library(name: "ObjcPackage", targets: ["ObjcPackage"]),
],
targets: [
.target(
name: "ObjcPackage",
path: "ObjcPackage/Source",
publicHeadersPath: "Public",
cSettings: [
.headerSearchPath("Public"),
.headerSearchPath("Internal"),
]
),
.testTarget(
name: "ObjcPackageTests",
dependencies: ["ObjcPackage"],
path: "ObjcPackageTests",
sources: ["Source"],
cSettings: [
.headerSearchPath("../ObjcPackage/Source/Internal")
]
)
]
)
2. Public header - ObjcPackage
// ObjcPackage.h
#import <Foundation/Foundation.h>
@interface ObjcPackage : NSObject
- (nullable instancetype)initWithTitle:(nonnull NSString *)title NS_DESIGNATED_INITIALIZER;
- (nonnull instancetype)init NS_UNAVAILABLE;
@property (nonnull, readonly, nonatomic, copy) NSString *title;
@end
3. Internal header - ObjcPackage
// ObjcPackage+Internal.h
#import <Foundation/Foundation.h>
#import "ObjcPackage.h"
/// Internal methods of ObjcPackage
@interface ObjcPackage ()
- (NSString *)generateInternalSecret;
@end
4. Implementation file - ObjcPackage
// ObjcPackage.m
#import "ObjcPackage.h"
#import "ObjcPackage+Internal.h"
@interface ObjcPackage()
@property (nonatomic, readwrite, copy) NSString *title;
@end
@implementation ObjcPackage
- (instancetype)initWithTitle:(NSString *)title {
self = [super init];
if (self != nil) {
self.title = title;
}
return self;
}
- (NSString *)generateInternalSecret {
return [NSString stringWithFormat:@"%@_internal_secret", self.title];
}
@end
5. Test example (ObjcPackageTests)
// ObjcPackageTests.swift
import Foundation
import XCTest
@testable import ObjcPackage
class ObjcPackageTests: XCTestCase {
private lazy var objcPackage = ObjcPackage(title: "A")
func testPublic() {
XCTAssertEqual(objcPackage?.title, "A")
}
func testInternal() {
// How to expose internal Objective-C header to the test package,
// without making it public?
// !!! - COMPILATION ERROR: - !!!
XCTAssertEqual(objcPackage.generateInternalSecret, "A_internal_secret")
}
}
Aucun commentaire:
Enregistrer un commentaire