Skip to content

Commit

Permalink
Add github action workflow to run tests
Browse files Browse the repository at this point in the history
* add section to readme for running tests

* add toc to readme

* use dedicated xcode build action

* fix compile error by renaming function in FMAPI.swift file

* split tests into dedicated test cases

* skip filter tests during CI

* add trigger for pushes to develop
  • Loading branch information
GrayedFox committed Sep 28, 2021
1 parent 58dc248 commit 4506746
Show file tree
Hide file tree
Showing 8 changed files with 352 additions and 155 deletions.
30 changes: 30 additions & 0 deletions .github/workflows/pull-request-tasks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Swift Integration Tests

on:
pull_request:
branches:
push:
branches:
- master
- develop

jobs:
test:
name: Tests
runs-on: macos-latest
strategy:
matrix:
destination: ['platform=iOS Simulator,OS=14.4,name=iPhone 12 Pro Max']

steps:
- name: Checkout Code
uses: actions/checkout@v2

- name: Build and Test
uses: sersoft-gmbh/xcodebuild-action@v1
with:
project: FantasmoSDK.xcodeproj
scheme: FantasmoSDKTests
destination: ${{ matrix.destination }}
action: test
skip-testing: 'FantasmoSDKTests/SDKFilterTests/testBlurFilter'
16 changes: 12 additions & 4 deletions FantasmoSDK.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
A0D0C57426BAB96100F35448 /* FMLocationDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A02EA34426B9154D00525308 /* FMLocationDelegate.swift */; };
A0D0C57526BAB96500F35448 /* FMZone.swift in Sources */ = {isa = PBXBuildFile; fileRef = 946838AA25921BF3005B1145 /* FMZone.swift */; };
A0D0C57726BD086E00F35448 /* MotionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0D0C57626BD086E00F35448 /* MotionManager.swift */; };
A0D5E88A26BA97DA00CE5B1C /* FantasmoSDKTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0D5E88926BA97DA00CE5B1C /* FantasmoSDKTests.swift */; };
A0D5E88A26BA97DA00CE5B1C /* SDKLocationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0D5E88926BA97DA00CE5B1C /* SDKLocationTests.swift */; };
A0D5E88C26BA97DA00CE5B1C /* FantasmoSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9468388B25921BAF005B1145 /* FantasmoSDK.framework */; };
A0D5E89226BA98E900CE5B1C /* CLLocation+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A02EA34A26BA7D8700525308 /* CLLocation+Extension.swift */; };
A0D5E89326BA98ED00CE5B1C /* Array+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A02EA34826B9253900525308 /* Array+Extension.swift */; };
Expand Down Expand Up @@ -92,6 +92,8 @@
A3CB77372636BDB8009625BB /* FMOrientation.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3CB77362636BDB8009625BB /* FMOrientation.swift */; };
A3CB773F263710D2009625BB /* simd_float4x4+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3CB773E263710D2009625BB /* simd_float4x4+Extension.swift */; };
A3CB774226372A9B009625BB /* simd_quatf+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3CB774126372A9B009625BB /* simd_quatf+Extension.swift */; };
FFA8586D2701D5D20069EB5D /* SDKFilterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFA8586B2701D5D20069EB5D /* SDKFilterTests.swift */; };
FFA8586E2701D5D20069EB5D /* SDKGeometricTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFA8586C2701D5D20069EB5D /* SDKGeometricTests.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -145,7 +147,7 @@
A02EA34A26BA7D8700525308 /* CLLocation+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CLLocation+Extension.swift"; sourceTree = "<group>"; };
A0D0C57626BD086E00F35448 /* MotionManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MotionManager.swift; sourceTree = "<group>"; };
A0D5E88726BA97DA00CE5B1C /* FantasmoSDKTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FantasmoSDKTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
A0D5E88926BA97DA00CE5B1C /* FantasmoSDKTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FantasmoSDKTests.swift; sourceTree = "<group>"; };
A0D5E88926BA97DA00CE5B1C /* SDKLocationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SDKLocationTests.swift; sourceTree = "<group>"; };
A0D5E88B26BA97DA00CE5B1C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
A30EBE08269F32B200E572FA /* AccumulatedARKitInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccumulatedARKitInfo.swift; sourceTree = "<group>"; };
A30EBE0B269F578E00E572FA /* TotalDeviceTranslationAccumulator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TotalDeviceTranslationAccumulator.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -176,6 +178,8 @@
A3CB773E263710D2009625BB /* simd_float4x4+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "simd_float4x4+Extension.swift"; sourceTree = "<group>"; };
A3CB774126372A9B009625BB /* simd_quatf+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "simd_quatf+Extension.swift"; sourceTree = "<group>"; };
A3EEC0852664EFC6008BCCF2 /* FMFrameFilter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FMFrameFilter.swift; sourceTree = "<group>"; };
FFA8586B2701D5D20069EB5D /* SDKFilterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SDKFilterTests.swift; sourceTree = "<group>"; };
FFA8586C2701D5D20069EB5D /* SDKGeometricTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SDKGeometricTests.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -330,7 +334,9 @@
A0D5E88826BA97DA00CE5B1C /* FantasmoSDKTests */ = {
isa = PBXGroup;
children = (
A0D5E88926BA97DA00CE5B1C /* FantasmoSDKTests.swift */,
FFA8586B2701D5D20069EB5D /* SDKFilterTests.swift */,
FFA8586C2701D5D20069EB5D /* SDKGeometricTests.swift */,
A0D5E88926BA97DA00CE5B1C /* SDKLocationTests.swift */,
A0D5E88B26BA97DA00CE5B1C /* Info.plist */,
4064380B26E7B1B100B38B45 /* UIImage+Extension.swift */,
);
Expand Down Expand Up @@ -599,18 +605,20 @@
A0D5E89326BA98ED00CE5B1C /* Array+Extension.swift in Sources */,
A0D5E89526BAA54300CE5B1C /* FMError.swift in Sources */,
A0D0C57426BAB96100F35448 /* FMLocationDelegate.swift in Sources */,
A0D5E88A26BA97DA00CE5B1C /* FantasmoSDKTests.swift in Sources */,
A0D5E88A26BA97DA00CE5B1C /* SDKLocationTests.swift in Sources */,
A0D5E89626BAA56100CE5B1C /* ErrorResponse.swift in Sources */,
4064380926E7ABA600B38B45 /* FMBlurFilter.swift in Sources */,
406437FF26E787A300B38B45 /* FMCamera.swift in Sources */,
4064380C26E7B1B100B38B45 /* UIImage+Extension.swift in Sources */,
4064380726E7A76A00B38B45 /* Angle.swift in Sources */,
A0D5E89226BA98E900CE5B1C /* CLLocation+Extension.swift in Sources */,
FFA8586D2701D5D20069EB5D /* SDKFilterTests.swift in Sources */,
4064380326E79C7A00B38B45 /* MockCamera.swift in Sources */,
406437FC26E7864300B38B45 /* FMFrame.swift in Sources */,
A0D5E89426BAA51F00CE5B1C /* FMLog.swift in Sources */,
A0D0C57326BAB95A00F35448 /* LocationFuser.swift in Sources */,
A0D0C57526BAB96500F35448 /* FMZone.swift in Sources */,
FFA8586E2701D5D20069EB5D /* SDKGeometricTests.swift in Sources */,
4064380126E79C0D00B38B45 /* MockFrame.swift in Sources */,
406437F826E7718700B38B45 /* FMMovementFilter.swift in Sources */,
4064380626E7A70E00B38B45 /* FMCameraPitchFilter.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1300"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A0D5E88626BA97DA00CE5B1C"
BuildableName = "FantasmoSDKTests.xctest"
BlueprintName = "FantasmoSDKTests"
ReferencedContainer = "container:FantasmoSDK.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
4 changes: 2 additions & 2 deletions FantasmoSDK/Classes/Network/FMApi.swift
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ class FMApi {
"total": events.total,
]

let imageResolution = imageResolution(from: frame, request: request)
let imageResolution = getImageResolution(from: frame, request: request)

var params = [
"intrinsics" : intrinsics.toJson(),
Expand Down Expand Up @@ -298,7 +298,7 @@ class FMApi {
/// - frame: Frame to return the resolution from
/// - request: Localization request struct
/// - Returns: Resolution as CGSize
private func imageResolution(from frame: ARFrame, request: FMLocalizationRequest) -> FMFrameResolution {
private func getImageResolution(from frame: ARFrame, request: FMLocalizationRequest) -> FMFrameResolution {
// mock if simulation
guard !request.isSimulation else {
let imageSize = MockData.imageResolution(request)
Expand Down
103 changes: 103 additions & 0 deletions FantasmoSDKTests/SDKFilterTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
//
// SDKFilterTests.swift
// FantasmoSDKTests
//
// Created by lucas kuzma on 8/4/21.
// Modified by che fisher on 27/9/21

import XCTest
import CoreLocation
import ARKit

class SDKFilterTests: XCTestCase {

override class func setUp() {
// Put setup code here that is run once (equal to mocha "before" hook)
}

override func setUpWithError() throws {
// Put setup code here is run before each test (equal to mocha "beforeEach" hook)
}

override func tearDownWithError() throws {
// Put teardown code that is run after each test case (equal to mocha "afterEach" hook)
}

override class func tearDown() {
// Put teardown code that is run once (equal to mocha "after" hook)
}

// note: this test will not fail and not throw an error code if the pixelBuffer assignment fails
func testMovementFilter() {
let filter = FMMovementFilter()
var transform = simd_float4x4(1)
var pixelBuffer: CVPixelBuffer? = nil
CVPixelBufferCreate(kCFAllocatorDefault, 64, 64, kCVPixelFormatType_OneComponent8, nil, &pixelBuffer)
if let pixelBuffer = pixelBuffer {
var frame = MockFrame(fmCamera: MockCamera(transform: transform), capturedImage: pixelBuffer)
XCTAssertEqual(filter.accepts(frame), .rejected(reason: .movingTooLittle))
transform = simd_float4x4(1.1)
frame = MockFrame(fmCamera: MockCamera(transform: transform), capturedImage: pixelBuffer)
XCTAssertEqual(filter.accepts(frame), .accepted)
transform = simd_float4x4(1.099)
XCTAssertEqual(filter.accepts(frame), .rejected(reason: .movingTooLittle))
} else {
print ("Couldn't allocate mock pixel buffer")
}
}

// note: this test will not fail and not throw an error code if the nonnilBuffer assignment fails
func testCameraPitchFilter() {
let filter = FMCameraPitchFilter()
var pixelBuffer: CVPixelBuffer? = nil
CVPixelBufferCreate(kCFAllocatorDefault, 64, 64, kCVPixelFormatType_OneComponent8, nil, &pixelBuffer)
var pitch : Float = deg2rad(-90)
if let nonnilBuffer = pixelBuffer {
var frame = MockFrame(fmCamera: MockCamera(pitch: pitch), capturedImage: nonnilBuffer)
XCTAssertEqual(filter.accepts(frame), .rejected(reason: .pitchTooLow))
pitch = deg2rad(-65)
frame = MockFrame(fmCamera: MockCamera(pitch: pitch), capturedImage: nonnilBuffer)
XCTAssertEqual(filter.accepts(frame), .accepted)
pitch = deg2rad(0)
frame = MockFrame(fmCamera: MockCamera(pitch: pitch), capturedImage: nonnilBuffer)
XCTAssertEqual(filter.accepts(frame), .accepted)
pitch = deg2rad(30)
frame = MockFrame(fmCamera: MockCamera(pitch: pitch), capturedImage: nonnilBuffer)
XCTAssertEqual(filter.accepts(frame), .accepted)
pitch = deg2rad(60)
frame = MockFrame(fmCamera: MockCamera(pitch: pitch), capturedImage: nonnilBuffer)
XCTAssertEqual(filter.accepts(frame), .rejected(reason: .pitchTooHigh))
} else {
print ("Couldn't allocate mock pixel buffer")
}
}

func testBlurFilter() {
let filter = FMBlurFilter()
let dayScan = UIImage(named: "dayScan", in: Bundle(for: type(of: self)), compatibleWith: nil)
let dayScanFrame = MockFrame(capturedImage: dayScan!.pixelBuffer()!)
let nightScan = UIImage(named: "nightScan", in: Bundle(for: type(of: self)), compatibleWith: nil)
let nightScanFrame = MockFrame(capturedImage: nightScan!.pixelBuffer()!)

// nighttime passes twice because of no throughput
XCTAssertEqual(filter.accepts(nightScanFrame), .accepted)
XCTAssertEqual(filter.accepts(nightScanFrame), .accepted)
// daytime passes because it has enough variance
XCTAssertEqual(filter.accepts(dayScanFrame), .accepted)
XCTAssertEqual(filter.accepts(dayScanFrame), .accepted)
XCTAssertEqual(filter.accepts(dayScanFrame), .accepted)
XCTAssertEqual(filter.accepts(dayScanFrame), .accepted)
// nighttime is rejected 6 times because it is too blurry and the throughput is superior to 0.25 on the last 8 frames
XCTAssertEqual(filter.accepts(nightScanFrame), .rejected(reason: .imageTooBlurry))
XCTAssertEqual(filter.accepts(nightScanFrame), .rejected(reason: .imageTooBlurry))
XCTAssertEqual(filter.accepts(nightScanFrame), .rejected(reason: .imageTooBlurry))
XCTAssertEqual(filter.accepts(nightScanFrame), .rejected(reason: .imageTooBlurry))
XCTAssertEqual(filter.accepts(nightScanFrame), .rejected(reason: .imageTooBlurry))
XCTAssertEqual(filter.accepts(nightScanFrame), .rejected(reason: .imageTooBlurry))
// on the 7th nighttime picture in a row, throughput gets back under 0.25 and it passes again
XCTAssertEqual(filter.accepts(nightScanFrame), .accepted)
XCTAssertEqual(filter.accepts(nightScanFrame), .accepted)
XCTAssertEqual(filter.accepts(nightScanFrame), .accepted)
XCTAssertEqual(filter.accepts(nightScanFrame), .accepted)
}
}
97 changes: 97 additions & 0 deletions FantasmoSDKTests/SDKGeometricTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
//
// SDKGeometricTests.swift
// FantasmoSDKTests
//
// Created by lucas kuzma on 8/4/21.
// Modified by che fisher on 27/9/21.

import XCTest
import CoreLocation
import ARKit

class SDKGeometricTests: XCTestCase {

override class func setUp() {
// Put setup code here that is run once (equal to mocha "before" hook)
}

override func setUpWithError() throws {
// Put setup code here is run before each test (equal to mocha "beforeEach" hook)
}

override func tearDownWithError() throws {
// Put teardown code that is run after each test case (equal to mocha "afterEach" hook)
}

override class func tearDown() {
// Put teardown code that is run once (equal to mocha "after" hook)
}

func testGeometricMedian() throws {
var locations: [CLLocation] = []
var median = CLLocation()
var expected = CLLocation()

locations.append(CLLocation(latitude: 0, longitude: 0))
median = CLLocation.geometricMedian(locations)
print(median.coordinate)

expected = CLLocation(latitude: 0, longitude: 0);
XCTAssertLessThan(median.degreeDistance(from: expected), 0.001)

locations = []
locations.append(CLLocation(latitude: 10, longitude: 0))
locations.append(CLLocation(latitude: -10, longitude: 0))
median = CLLocation.geometricMedian(locations)
print(median.coordinate)

expected = CLLocation(latitude: 0, longitude: 0);
XCTAssertLessThan(median.degreeDistance(from: expected), 0.001)

locations.append(CLLocation(latitude: 0, longitude: 10))
median = CLLocation.geometricMedian(locations)
print(median.coordinate)

expected = CLLocation(latitude: 0, longitude: 5.77);
XCTAssertLessThan(median.degreeDistance(from: expected), 0.01)

locations = []
locations.append(CLLocation(latitude: 10, longitude: 10))
locations.append(CLLocation(latitude: 20, longitude: 10))
locations.append(CLLocation(latitude: 10, longitude: 20))
locations.append(CLLocation(latitude: 20, longitude: 20))
median = CLLocation.geometricMedian(locations)
print(median.coordinate)

expected = CLLocation(latitude: 15, longitude: 15);
XCTAssertLessThan(median.degreeDistance(from: expected), 0.01)

locations.append(CLLocation(latitude: 15, longitude: 15))
median = CLLocation.geometricMedian(locations)
print(median.coordinate)

XCTAssertLessThan(median.degreeDistance(from: expected), 0.01)
}

func testGeometricMedianColinear() throws {
var locations: [CLLocation] = []
var median = CLLocation()
var expected = CLLocation()

locations = []
locations.append(CLLocation(latitude: 0, longitude: 0))
locations.append(CLLocation(latitude: 0, longitude: 10))
median = CLLocation.geometricMedian(locations)
print(median.coordinate)

expected = CLLocation(latitude: 0, longitude: 5);
XCTAssertLessThan(median.degreeDistance(from: expected), 0.01)

locations.append(CLLocation(latitude: 0, longitude: 20))
median = CLLocation.geometricMedian(locations)
print(median.coordinate)

expected = CLLocation(latitude: 0, longitude: 10);
XCTAssertLessThan(median.degreeDistance(from: expected), 0.01)
}
}
Loading

0 comments on commit 4506746

Please sign in to comment.