Skip to content

Commit

Permalink
Merge pull request #2 from KaoruMuta/feature/test
Browse files Browse the repository at this point in the history
test: add unittest and uitest to improve code coverage
  • Loading branch information
KaoruMuta authored Jan 12, 2021
2 parents f6fdafd + 490b11d commit 4f87473
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 18 deletions.
14 changes: 7 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ jobs:
- platform=iOS Simulator,name=iPhone 11,OS=13.2.2
runs-on: macos-10.15
steps:
- uses: actions/checkout@v2
- name: Select Xcode
run: sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode_version }}.app/Contents/Developer
- name: Check Xcode version
run: xcodebuild -version
- name: Run tests
run: xcodebuild -project IGStoryButtonKit.xcodeproj -scheme IGStoryButtonKit -sdk iphonesimulator -destination "${{ matrix.destination }}" test
- uses: actions/checkout@v2
- name: Select Xcode
run: sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode_version }}.app/Contents/Developer
- name: Check Xcode version
run: xcodebuild -version
- name: Run tests
run: xcodebuild -project IGStoryButtonKit.xcodeproj -scheme IGStoryButtonKit -sdk iphonesimulator -destination "${{ matrix.destination }}" test
36 changes: 36 additions & 0 deletions IGStoryButtonKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
/* Begin PBXBuildFile section */
E20FF10C25A18D59002E39FA /* Const.swift in Sources */ = {isa = PBXBuildFile; fileRef = E20FF10A25A18D59002E39FA /* Const.swift */; };
E20FF10D25A18D59002E39FA /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E20FF10B25A18D59002E39FA /* Extensions.swift */; };
E2599B9325AC5D050093E009 /* MockViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2599B9225AC5D050093E009 /* MockViewController.swift */; };
E27115D425A2CD6500B6ACA6 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E27115D325A2CD6500B6ACA6 /* ContentView.swift */; };
E27115E725A2E1FC00B6ACA6 /* StoryCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E27115E525A2E1FC00B6ACA6 /* StoryCell.swift */; };
E27115E825A2E1FC00B6ACA6 /* StoryCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = E27115E625A2E1FC00B6ACA6 /* StoryCell.xib */; };
Expand All @@ -19,6 +20,8 @@
E271163025A485B600B6ACA6 /* Const.swift in Sources */ = {isa = PBXBuildFile; fileRef = E20FF10A25A18D59002E39FA /* Const.swift */; };
E271163325A485C600B6ACA6 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E20FF10B25A18D59002E39FA /* Extensions.swift */; };
E27C03D525A1EEF700A1D1FC /* StatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E27C03D425A1EEF700A1D1FC /* StatusView.swift */; };
E2C63AE025AD3D6300F76AD7 /* Precondition.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2C63ADF25AD3D6300F76AD7 /* Precondition.swift */; };
E2C63AE725AD3E9800F76AD7 /* XCTest+Precondition.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2C63AE625AD3E9800F76AD7 /* XCTest+Precondition.swift */; };
E2CBC2F3259CD73700B92BA4 /* IGStoryButtonKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E2CBC2E9259CD73700B92BA4 /* IGStoryButtonKit.framework */; };
E2CBC2F8259CD73700B92BA4 /* IGStoryButtonTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2CBC2F7259CD73700B92BA4 /* IGStoryButtonTest.swift */; };
E2CBC2FA259CD73700B92BA4 /* IGStoryButtonKit.h in Headers */ = {isa = PBXBuildFile; fileRef = E2CBC2EC259CD73700B92BA4 /* IGStoryButtonKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
Expand Down Expand Up @@ -68,11 +71,14 @@
/* Begin PBXFileReference section */
E20FF10A25A18D59002E39FA /* Const.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Const.swift; sourceTree = "<group>"; };
E20FF10B25A18D59002E39FA /* Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = "<group>"; };
E2599B9225AC5D050093E009 /* MockViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockViewController.swift; sourceTree = "<group>"; };
E27115D325A2CD6500B6ACA6 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
E27115E525A2E1FC00B6ACA6 /* StoryCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoryCell.swift; sourceTree = "<group>"; };
E27115E625A2E1FC00B6ACA6 /* StoryCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = StoryCell.xib; sourceTree = "<group>"; };
E27115F925A41E1300B6ACA6 /* Story.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Story.swift; sourceTree = "<group>"; };
E27C03D425A1EEF700A1D1FC /* StatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusView.swift; sourceTree = "<group>"; };
E2C63ADF25AD3D6300F76AD7 /* Precondition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Precondition.swift; sourceTree = "<group>"; };
E2C63AE625AD3E9800F76AD7 /* XCTest+Precondition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "XCTest+Precondition.swift"; sourceTree = "<group>"; };
E2CBC2E9259CD73700B92BA4 /* IGStoryButtonKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = IGStoryButtonKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
E2CBC2EC259CD73700B92BA4 /* IGStoryButtonKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IGStoryButtonKit.h; sourceTree = "<group>"; };
E2CBC2ED259CD73700B92BA4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
Expand Down Expand Up @@ -118,6 +124,22 @@
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
E2490E2E25AD4063000DA950 /* Extension */ = {
isa = PBXGroup;
children = (
E2C63AE625AD3E9800F76AD7 /* XCTest+Precondition.swift */,
);
path = Extension;
sourceTree = "<group>";
};
E2490E3325AD4893000DA950 /* Mock */ = {
isa = PBXGroup;
children = (
E2599B9225AC5D050093E009 /* MockViewController.swift */,
);
path = Mock;
sourceTree = "<group>";
};
E271161B25A458D200B6ACA6 /* Model */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -147,6 +169,16 @@
path = Application;
sourceTree = "<group>";
};
E2C63ADE25AD3D1E00F76AD7 /* Helper */ = {
isa = PBXGroup;
children = (
E2490E3325AD4893000DA950 /* Mock */,
E2490E2E25AD4063000DA950 /* Extension */,
E2C63ADF25AD3D6300F76AD7 /* Precondition.swift */,
);
path = Helper;
sourceTree = "<group>";
};
E2CBC2DF259CD73700B92BA4 = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -185,6 +217,7 @@
E2CBC2F6259CD73700B92BA4 /* IGStoryButtonKitTests */ = {
isa = PBXGroup;
children = (
E2C63ADE25AD3D1E00F76AD7 /* Helper */,
E2CBC2F7259CD73700B92BA4 /* IGStoryButtonTest.swift */,
E2CBC2F9259CD73700B92BA4 /* Info.plist */,
);
Expand Down Expand Up @@ -398,8 +431,11 @@
buildActionMask = 2147483647;
files = (
E2CBC2F8259CD73700B92BA4 /* IGStoryButtonTest.swift in Sources */,
E2C63AE725AD3E9800F76AD7 /* XCTest+Precondition.swift in Sources */,
E271163325A485C600B6ACA6 /* Extensions.swift in Sources */,
E271162725A482D300B6ACA6 /* IGStoryButton.swift in Sources */,
E2C63AE025AD3D6300F76AD7 /* Precondition.swift in Sources */,
E2599B9325AC5D050093E009 /* MockViewController.swift in Sources */,
E271162D25A4859B00B6ACA6 /* ContentView.swift in Sources */,
E271162A25A4859900B6ACA6 /* StatusView.swift in Sources */,
E271163025A485B600B6ACA6 /* Const.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
shouldUseLaunchSchemeArgsEnv = "YES"
codeCoverageEnabled = "YES">
<Testables>
<TestableReference
skipped = "NO">
Expand Down
8 changes: 7 additions & 1 deletion IGStoryButtonKit/IGStoryButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ public protocol IGStoryButtonDelegate: class {

override public func layoutSubviews() {
super.layoutSubviews()
assert(frame.width == frame.height, "The size of width and height are required to be equal")
validate(width: frame.width, height: frame.height)
// arrange layout
configureLayout()
}
Expand All @@ -164,6 +164,12 @@ public protocol IGStoryButtonDelegate: class {
}
}

public extension IGStoryButton {
func validate(width: CGFloat, height: CGFloat) {
precondition(width == height, "The size of width and height are required to be equal")
}
}

// TODO: implemented richer animation like instagram story...
public extension IGStoryButton {
/// execute circle animation
Expand Down
25 changes: 25 additions & 0 deletions IGStoryButtonKitTests/Helper/Extension/XCTest+Precondition.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// XCTest+Precondition.swift
// IGStoryButtonKitTests
//
// Created by k_muta on 2021/01/12.
//

import XCTest

extension XCTestCase {
func expectPreconditionFailure(expectedMessage: String, block: () -> ()) {
let expect = expectation(description: "failing precondition")
preconditionClosure = {
(condition, message, file, line) in
if !condition {
expect.fulfill()
XCTAssertEqual(message, expectedMessage, "precondition message didn't match", file: file, line: line)
}
}
block()
waitForExpectations(timeout: 2.0, handler: nil)
preconditionClosure = defaultPreconditionClosure
}
}

21 changes: 21 additions & 0 deletions IGStoryButtonKitTests/Helper/Mock/MockViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// MockViewController.swift
// IGStoryButtonKitTests
//
// Created by k_muta on 2021/01/11.
//

import UIKit

final class MockViewController: UIViewController, IGStoryButtonDelegate {
var isTapped: Bool = false
var isLongPressed: Bool = false

func didTapped() {
isTapped = true
}

func didLongPressed() {
isLongPressed = true
}
}
15 changes: 15 additions & 0 deletions IGStoryButtonKitTests/Helper/Precondition.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// Precondition.swift
// IGStoryButtonKitTests
//
// Created by k_muta on 2021/01/12.
//

import Foundation

func precondition(_ condition: @autoclosure () -> Bool, _ message: @autoclosure () -> String = String(), file: StaticString = #file, line: UInt = #line) {
preconditionClosure(condition(), message(), file, line)
}

var preconditionClosure: (Bool, String, StaticString, UInt) -> () = defaultPreconditionClosure
let defaultPreconditionClosure = { Swift.precondition($0, $1, file: $2, line: $3) }
44 changes: 35 additions & 9 deletions IGStoryButtonKitTests/IGStoryButtonTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,55 @@ import XCTest
@testable import IGStoryButtonKit

final class IGStoryButtonTests: XCTestCase {
// MARK: - Unit tests
func testManipulateType() {
// MARK: - Unit tests for IGStoryButton
func testInitWithFrame() {
let storyButton = IGStoryButton()
XCTAssertEqual(storyButton.frame, .zero)
storyButton.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
XCTAssertEqual(storyButton.frame.width, 100)
XCTAssertEqual(storyButton.frame.height, 100)
}

func testExpectPreconditionFailure() {
let frame = CGRect(x: 0, y: 0, width: 100, height: 80)
let storyButton = IGStoryButton(frame: frame, displayType: .none, colorType: .clear, image: UIImage())
expectPreconditionFailure(expectedMessage: "The size of width and height are required to be equal") {
storyButton.validate(width: frame.width, height: frame.height)
}
}

func testDisplayTypeAndColorTypeIsValid() {
let storyButton = IGStoryButton(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
let mockImage: UIImage? = .init()

storyButton.condition = .init(display: .seen, color: .black)
XCTAssertEqual(storyButton.colorType, .black)
XCTAssertNotEqual(storyButton.colorType, .default)
storyButton.condition = .init(display: .seen)
XCTAssertEqual(storyButton.displayType, .seen)
XCTAssertNotEqual(storyButton.displayType, .unseen)
XCTAssertEqual(storyButton.colorType, nil)

storyButton.condition = .init(display: .unseen, color: .default)
XCTAssertEqual(storyButton.displayType, .unseen)
XCTAssertEqual(storyButton.colorType, .default)

storyButton.condition = .init(display: .status(type: .color(of: .green)))
XCTAssertEqual(storyButton.colorType, nil)
XCTAssertEqual(storyButton.displayType, .status(type: .color(of: .green)))
XCTAssertNotEqual(storyButton.displayType, .status(type: .color(of: .red)))

storyButton.condition = .init(display: .status(type: .image(of: mockImage)), color: .default)
storyButton.condition = .init(display: .status(type: .image(of: mockImage)))
XCTAssertEqual(storyButton.displayType, .status(type: .image(of: mockImage)))
XCTAssertNotEqual(storyButton.displayType, .status(type: .image(of: nil)))

storyButton.condition = .init(display: .none, color: .custom(colors: [.red, .green]))
XCTAssertEqual(storyButton.colorType, .custom(colors: [.red, .green]))
XCTAssertNotEqual(storyButton.colorType, .custom(colors: [.red]))
}


func testButtonEventIsCatched() {
let storyButton = IGStoryButton()
let viewController = MockViewController()
storyButton.delegate = viewController
storyButton.delegate?.didTapped()
storyButton.delegate?.didLongPressed()
XCTAssertTrue(viewController.isTapped)
XCTAssertTrue(viewController.isLongPressed)
}
}

0 comments on commit 4f87473

Please sign in to comment.