Skip to content

Commit b2478c6

Browse files
jaeoptthomaszurkan-optimizely
authored andcommitted
add tests for Optimizely coverage (#225)
* add tests to cover Optimizely files * (wip) add tests for coverage * (wip) add tests for coverage * (wip) add tests for Optimizely coverage * (wip) tests for coverage * add tests for OptimizelyClient code coverage * (wip) add tests for OptmizelyClient-ObjC coverage * add tests for Optimizely coverage * add tests for Optimizely coverage * changes per review comments * rename tests per review comments
1 parent f081387 commit b2478c6

File tree

12 files changed

+683
-54
lines changed

12 files changed

+683
-54
lines changed

OptimizelySDK/Customization/DefaultEventDispatcher.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,9 @@ open class DefaultEventDispatcher: BackgroundingCallbacks, OPTEventDispatcher {
7575
open func dispatchEvent(event: EventForDispatch, completionHandler: DispatchCompletionHandler?) {
7676
dataStore.save(item: event)
7777

78-
// TODO: use or clean up completionHandler
79-
8078
setTimer()
79+
80+
completionHandler?(.success(event.body))
8181
}
8282

8383
// notify group used to ensure that the sendEvent is synchronous.

OptimizelySDK/Data Model/ProjectConfig.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,10 @@ class ProjectConfig {
8888
} catch {
8989
throw OptimizelyError.dataFileInvalid
9090
}
91+
9192
if !isValidVersion(version: self.project.version) {
9293
throw OptimizelyError.dataFileVersionInvalid(self.project.version)
9394
}
94-
9595
}
9696

9797
convenience init(datafile: String) throws {
@@ -184,6 +184,13 @@ extension ProjectConfig {
184184
return featureFlagKeyMap[key]
185185
}
186186

187+
/**
188+
* Get all Feature Flag objects.
189+
*/
190+
func getFeatureFlags() -> [FeatureFlag] {
191+
return project.featureFlags
192+
}
193+
187194
/**
188195
* Get a Rollout object for an Id.
189196
*/

OptimizelySDK/Optimizely/OptimizelyClient.swift

Lines changed: 9 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,8 @@ open class OptimizelyClient: NSObject {
107107
try self.configSDK(datafile: datafile)
108108

109109
completion?(result)
110-
} catch let error as OptimizelyError {
111-
completion?(.failure(error))
112110
} catch {
113-
print("Invalid error types: \(error)")
114-
completion?(.failure(OptimizelyError.datafileDownloadFailed("Unknown")))
111+
completion?(.failure(error as! OptimizelyError))
115112
}
116113
}
117114
}
@@ -124,10 +121,7 @@ open class OptimizelyClient: NSObject {
124121
/// A cached copy from previous download is used if it's available.
125122
/// The datafile will be updated from the server in the background thread.
126123
public func start(datafile: String) throws {
127-
guard let datafileData = datafile.data(using: .utf8) else {
128-
throw OptimizelyError.dataFileInvalid
129-
}
130-
124+
let datafileData = Data(datafile.utf8)
131125
try start(datafile: datafileData)
132126
}
133127

@@ -154,10 +148,7 @@ open class OptimizelyClient: NSObject {
154148
func configSDK(datafile: Data) throws {
155149
do {
156150
self.config = try ProjectConfig(datafile: datafile)
157-
158-
// this isn't really necessary because the try would throw if there is a problem. But, we want to avoid using bang so we do another let binding.
159-
guard let config = self.config else { throw OptimizelyError.dataFileInvalid }
160-
151+
161152
datafileHandler.startUpdates(sdkKey: self.sdkKey) { data in
162153
// new datafile came in...
163154
self.reInitLock.wait(); defer { self.reInitLock.signal() }
@@ -171,8 +162,7 @@ open class OptimizelyClient: NSObject {
171162

172163
// call reinit on the services we know we are reinitializing.
173164

174-
for component in HandlerRegistryService.shared.lookupComponents(sdkKey: self.sdkKey) ?? [] {
175-
guard let component = component else { continue }
165+
for component in HandlerRegistryService.shared.lookupComponents(sdkKey: self.sdkKey) {
176166
HandlerRegistryService.shared.reInitializeComponent(service: component, sdkKey: self.sdkKey)
177167
}
178168

@@ -183,13 +173,11 @@ open class OptimizelyClient: NSObject {
183173

184174
}
185175
}
186-
} catch let error as OptimizelyError {
176+
} catch {
187177
// .datafileInvalid
188178
// .datafaileVersionInvalid
189179
// .datafaileLoadingFailed
190180
throw error
191-
} catch { // DecodingError, etc.
192-
throw OptimizelyError.dataFileInvalid
193181
}
194182
}
195183

@@ -604,11 +592,7 @@ open class OptimizelyClient: NSObject {
604592
return enabledFeatures
605593
}
606594

607-
guard let featureFlags = config.project?.featureFlags else {
608-
return enabledFeatures
609-
}
610-
611-
enabledFeatures = featureFlags.filter {
595+
enabledFeatures = config.getFeatureFlags().filter {
612596
isFeatureEnabled(featureKey: $0.key, userId: userId, attributes: attributes)
613597
}.map { $0.key }
614598

@@ -660,14 +644,7 @@ extension OptimizelyClient {
660644
// because we are batching events, we cannot guarantee that the completion handler will be
661645
// called. So, for now, we are queuing and calling onActivate. Maybe we should mention that
662646
// onActivate only means the event has been queued and not necessarily sent.
663-
self.eventDispatcher.dispatchEvent(event: event) { result in
664-
switch result {
665-
case .failure:
666-
break
667-
case .success:
668-
break
669-
}
670-
}
647+
self.eventDispatcher.dispatchEvent(event: event, completionHandler: nil)
671648

672649
self.notificationCenter.sendNotifications(type: NotificationType.activate.rawValue, args: [experiment, userId, attributes, variation, ["url": event.url as Any, "body": event.body as Any]])
673650

@@ -693,14 +670,8 @@ extension OptimizelyClient {
693670
// because we are batching events, we cannot guarantee that the completion handler will be
694671
// called. So, for now, we are queuing and calling onTrack. Maybe we should mention that
695672
// onTrack only means the event has been queued and not necessarily sent.
696-
self.eventDispatcher.dispatchEvent(event: event) { result in
697-
switch result {
698-
case .failure:
699-
break
700-
case .success:
701-
break
702-
}
703-
}
673+
self.eventDispatcher.dispatchEvent(event: event, completionHandler: nil)
674+
704675
self.notificationCenter.sendNotifications(type: NotificationType.track.rawValue, args: [eventKey, userId, attributes, eventTags, ["url": event.url as Any, "body": event.body as Any]])
705676

706677
}

OptimizelySDK/OptimizelySwiftSDK.xcodeproj/project.pbxproj

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1029,6 +1029,7 @@
10291029
6EBAEB7C21E3FEF900D13AA9 /* Optimizely.h in Headers */ = {isa = PBXBuildFile; fileRef = 6EBAEB6E21E3FEF800D13AA9 /* Optimizely.h */; settings = {ATTRIBUTES = (Public, ); }; };
10301030
6EC126172218D97E00C1FC97 /* OTUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E7FC6A222121D27009A171F /* OTUtils.swift */; };
10311031
6EC126182218D97F00C1FC97 /* OTUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E7FC6A222121D27009A171F /* OTUtils.swift */; };
1032+
6EC2FE5022AEDD2D00B6C44D /* OptimizelyClientTests_ObjcOthers.m in Sources */ = {isa = PBXBuildFile; fileRef = 6EC2FE4F22AEDD2D00B6C44D /* OptimizelyClientTests_ObjcOthers.m */; };
10321033
6EC8D011225CFAB2000B20A4 /* EventDispatcherTests_Batch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EC8D010225CFAB2000B20A4 /* EventDispatcherTests_Batch.swift */; };
10331034
6EC8D012225CFAB2000B20A4 /* EventDispatcherTests_Batch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EC8D010225CFAB2000B20A4 /* EventDispatcherTests_Batch.swift */; };
10341035
6ED1B8FA2225AA6500C4C774 /* DefaultUserProfileServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6ED1B8F92225AA6500C4C774 /* DefaultUserProfileServiceTests.swift */; };
@@ -1071,6 +1072,8 @@
10711072
6EF4B4E422383632002DE8B6 /* AtomicProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BE644EC223821D3009A5D1D /* AtomicProperty.swift */; };
10721073
6EF4B4E5223836C1002DE8B6 /* BackgroundingCallbacks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B77D05722370526005AA83F /* BackgroundingCallbacks.swift */; };
10731074
6EF4B4E6223836C1002DE8B6 /* BackgroundingCallbacks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B77D05722370526005AA83F /* BackgroundingCallbacks.swift */; };
1075+
6EFAB05A22A5D51100800884 /* OptimizelyClientTests_Others.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EFAB05922A5D51100800884 /* OptimizelyClientTests_Others.swift */; };
1076+
6EFAB06822A6E75000800884 /* OptimizelyErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EFAB06722A6E75000800884 /* OptimizelyErrorTests.swift */; };
10741077
7D709BF221602C0F885D19AD /* Pods_OptimizelySwiftSDK_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1B04909B698F3888941B202B /* Pods_OptimizelySwiftSDK_tvOS.framework */; };
10751078
C72BD1BB22B12E63003A55E4 /* LoggerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C72BD1BA22B12E63003A55E4 /* LoggerTests.swift */; };
10761079
C72BD1BC22B12E63003A55E4 /* LoggerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C72BD1BA22B12E63003A55E4 /* LoggerTests.swift */; };
@@ -1079,6 +1082,7 @@
10791082
C737D52822ABEFCA0081AFEB /* OptimizelyErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C737D52522ABEFCA0081AFEB /* OptimizelyErrorTests.swift */; };
10801083
C737D52922ABEFCA0081AFEB /* OptimizelyErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C737D52522ABEFCA0081AFEB /* OptimizelyErrorTests.swift */; };
10811084
C79F9D872251F597002B0BC9 /* DecisionListenerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C79F9D852251F58F002B0BC9 /* DecisionListenerTests.swift */; };
1085+
E10C7EAB88DD4B2C71417ED5 /* Pods_OptimizelySwiftSDK_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1B04909B698F3888941B202B /* Pods_OptimizelySwiftSDK_tvOS.framework */; };
10821086
FB96C3F6D4FD5F6E43CB22E6 /* Pods_OptimizelySwiftSDK_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 574006F0CB4FA41286C13DC7 /* Pods_OptimizelySwiftSDK_iOS.framework */; };
10831087
/* End PBXBuildFile section */
10841088

@@ -1311,6 +1315,7 @@
13111315
6EBAEB6E21E3FEF800D13AA9 /* Optimizely.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Optimizely.h; sourceTree = "<group>"; };
13121316
6EBAEB6F21E3FEF800D13AA9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
13131317
6EBAEB7421E3FEF900D13AA9 /* OptimizelyTests-iOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "OptimizelyTests-iOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
1318+
6EC2FE4F22AEDD2D00B6C44D /* OptimizelyClientTests_ObjcOthers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OptimizelyClientTests_ObjcOthers.m; sourceTree = "<group>"; };
13141319
6EC2FE952243F727005A94F7 /* x-V2TestDatafile.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "x-V2TestDatafile.json"; sourceTree = "<group>"; };
13151320
6EC2FE962243F728005A94F7 /* x-test_data_25_experiments.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "x-test_data_25_experiments.json"; sourceTree = "<group>"; };
13161321
6EC2FE972243F728005A94F7 /* x-UnsupportedVersionDatafile.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "x-UnsupportedVersionDatafile.json"; sourceTree = "<group>"; };
@@ -1330,6 +1335,8 @@
13301335
6EDE919822273DD700840112 /* optimizely_6372300739_v4.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = optimizely_6372300739_v4.json; sourceTree = "<group>"; };
13311336
6EDE91A122273DD700840112 /* typed_audience_datafile.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = typed_audience_datafile.json; sourceTree = "<group>"; };
13321337
6EDE91A422273DD700840112 /* UnsupportedVersionDatafile.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = UnsupportedVersionDatafile.json; sourceTree = "<group>"; };
1338+
6EFAB05922A5D51100800884 /* OptimizelyClientTests_Others.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptimizelyClientTests_Others.swift; sourceTree = "<group>"; };
1339+
6EFAB06722A6E75000800884 /* OptimizelyErrorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptimizelyErrorTests.swift; sourceTree = "<group>"; };
13331340
7C392E11ABAA00DDA1F864B9 /* Pods_OptimizelyTests_APIs_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_OptimizelyTests_APIs_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
13341341
8254240CC67030C578E7F13A /* Pods-OptimizelySwiftSDK-iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OptimizelySwiftSDK-iOS.release.xcconfig"; path = "Target Support Files/Pods-OptimizelySwiftSDK-iOS/Pods-OptimizelySwiftSDK-iOS.release.xcconfig"; sourceTree = "<group>"; };
13351342
8268B42D4E084F1ED5D05151 /* Pods_OptimizelyTests_Common_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_OptimizelyTests_Common_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -1356,7 +1363,7 @@
13561363
isa = PBXFrameworksBuildPhase;
13571364
buildActionMask = 2147483647;
13581365
files = (
1359-
7D709BF221602C0F885D19AD /* Pods_OptimizelySwiftSDK_tvOS.framework in Frameworks */,
1366+
E10C7EAB88DD4B2C71417ED5 /* Pods_OptimizelySwiftSDK_tvOS.framework in Frameworks */,
13601367
);
13611368
runOnlyForDeploymentPostprocessing = 0;
13621369
};
@@ -1743,6 +1750,9 @@
17431750
6E8CB5C8224C461A00B8CB7A /* OptimizelyClientTests_Variables.swift */,
17441751
0B8F537B223FFB0500C56082 /* OptimizelyClientTests_Group.swift */,
17451752
6E341E2F22615D1F005416B7 /* OptimizelyClientTests_ObjcAPIs.m */,
1753+
6EC2FE4F22AEDD2D00B6C44D /* OptimizelyClientTests_ObjcOthers.m */,
1754+
6EFAB05922A5D51100800884 /* OptimizelyClientTests_Others.swift */,
1755+
6EFAB06722A6E75000800884 /* OptimizelyErrorTests.swift */,
17461756
0B86666422A83EFC009CD211 /* OptimizelyClientTests_DatafileHandler.swift */,
17471757
);
17481758
path = "OptimizelyTests-APIs";
@@ -2798,13 +2808,15 @@
27982808
6E636C192236CBE400AF3CEF /* OTUtils.swift in Sources */,
27992809
6E636C622237182000AF3CEF /* OptimizelyClientTests_Evaluation.swift in Sources */,
28002810
6E636C152236CA4300AF3CEF /* OptimizelyClientTests_Invalid.swift in Sources */,
2811+
6EFAB06822A6E75000800884 /* OptimizelyErrorTests.swift in Sources */,
28012812
6E636BEF2236C9BC00AF3CEF /* FeatureFlag.swift in Sources */,
28022813
6E636BEE2236C9BC00AF3CEF /* Experiment.swift in Sources */,
28032814
6E636BF52236C9BC00AF3CEF /* Event.swift in Sources */,
28042815
6E636BEA2236C9BC00AF3CEF /* ProjectConfig.swift in Sources */,
28052816
6EDBCE1D2272333B009DF724 /* OptimizelyClient+ObjC.swift in Sources */,
28062817
6E636BCF2236C9A800AF3CEF /* OPTDatafileHandler.swift in Sources */,
28072818
6E636BD02236C9A800AF3CEF /* OPTNotificationCenter.swift in Sources */,
2819+
6EC2FE5022AEDD2D00B6C44D /* OptimizelyClientTests_ObjcOthers.m in Sources */,
28082820
6E8D32172266905D00478458 /* LogMessage.swift in Sources */,
28092821
6E636BDD2236C9B100AF3CEF /* BatchEvent.swift in Sources */,
28102822
6E636BE42236C9B700AF3CEF /* AttributeValue.swift in Sources */,
@@ -2828,6 +2840,7 @@
28282840
6E636BBD2236C99300AF3CEF /* DataStoreMemory.swift in Sources */,
28292841
6E636BF42236C9BC00AF3CEF /* FeatureVariable.swift in Sources */,
28302842
6EA0721F223AC72D00F447CF /* Utils.swift in Sources */,
2843+
6EFAB05A22A5D51100800884 /* OptimizelyClientTests_Others.swift in Sources */,
28312844
6E636C0C2236C9CA00AF3CEF /* MurmurHash3.swift in Sources */,
28322845
6E636BAE2236C98300AF3CEF /* DefaultLogger.swift in Sources */,
28332846
6E636BCD2236C9A800AF3CEF /* OPTDecisionService.swift in Sources */,

OptimizelySDK/OptimizelyTests/OptimizelyTests-APIs/OptimizelyClientTests_Invalid.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ class OptimizelyClientTests_Invalid: XCTestCase {
3535
let invalidDatafile = "{\"version\": \"4\"}"
3636
try? self.optimizely.start(datafile: invalidDatafile)
3737
}
38+
}
39+
40+
// MARK: - ManagerNonInitialized
41+
42+
extension OptimizelyClientTests_Invalid {
3843

3944
func testActivate_WhenManagerNonInitialized() {
4045
let variationKey: String? = try? self.optimizely.activate(experimentKey: kExperimentKey, userId: kUserId)
@@ -105,6 +110,12 @@ class OptimizelyClientTests_Invalid: XCTestCase {
105110
XCTAssert(true)
106111
}
107112
}
113+
114+
}
115+
116+
// MARK: - Invalid Keys
117+
118+
extension OptimizelyClientTests_Invalid {
108119

109120
func testTrack_WhenEventNotInDatafile() {
110121
do {
@@ -116,3 +127,5 @@ class OptimizelyClientTests_Invalid: XCTestCase {
116127
}
117128

118129
}
130+
131+

OptimizelySDK/OptimizelyTests/OptimizelyTests-APIs/OptimizelyClientTests_ObjcAPIs.m

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ @interface OptimizelyClientTests_ObjcAPIs : XCTestCase
4848
@property(nonatomic) NSDictionary * attributes;
4949
@end
5050

51-
// MARK: - Customization Modules Protocols
51+
// MARK: - Custom Logger
5252

5353
@interface TestOPTLogger: NSObject <OPTLogger>
5454
@end
@@ -67,6 +67,8 @@ + (void)setLogLevel:(enum OptimizelyLogLevel)newValue {
6767
}
6868
@end
6969

70+
// MARK: - Custom EventDispatcher
71+
7072
@interface TestOPTEventDispatcher: NSObject <OPTEventDispatcher>
7173
@end
7274

@@ -80,6 +82,8 @@ - (void)flushEvents {
8082
}
8183
@end
8284

85+
// MARK: - Custom UserProfileService
86+
8387
@interface TestOPTUserProfileService: NSObject<OPTUserProfileService>
8488
@end
8589

@@ -214,11 +218,6 @@ - (void)testCustomizationAPIs {
214218
TestOPTEventDispatcher *eventDispatcher = [[TestOPTEventDispatcher alloc] init];
215219
TestOPTUserProfileService *userProfileService = [[TestOPTUserProfileService alloc] init];
216220

217-
// check event init and members avialable to ObjC
218-
EventForDispatch *event = [[EventForDispatch alloc] initWithUrl:nil body:[NSData new]];
219-
XCTAssertNotNil(event.url);
220-
XCTAssert(event.body.length==0);
221-
222221
// check all SDK initialization APIs for ObjC
223222
self.optimizely = [[OptimizelyClient alloc] initWithSdkKey:kSdkKey];
224223

0 commit comments

Comments
 (0)