Skip to content

[SR-1417] Add non-optional overloads of XCTAssertEqual and XCTAssertN… #110

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 35 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
36b2ef3
Add an option to specify the install prefix for CoreFoundation depend…
bryanpkc May 10, 2016
22dbc8c
[SR-1417] Add non-optional overloads of XCTAssertEqual and XCTAssertN…
nsalmoria May 12, 2016
6518ecb
_XCTestObservation -> XCTestInternalObservation and move to separate …
briancroom May 13, 2016
7482bd3
Move XCTestCase async methods to their new home sweet file home.
briancroom May 13, 2016
fcb64c5
Sort source file references by name in the xcodeproj.
briancroom May 13, 2016
82edc2b
[Tests] Automatically substitute [[@LINE]] numbers
modocache May 16, 2016
ccaff50
Merge pull request #112 from modocache/line-offsets
briancroom May 16, 2016
37b9feb
[Tests] Use line number offsets for assertions
modocache May 16, 2016
eee815e
Merge pull request #111 from briancroom/extract-files
briancroom May 16, 2016
206f746
Merge pull request #113 from modocache/update-test-line-numbers
modocache May 16, 2016
fd10d41
[SR-1417] Add non-optional overloads of XCTAssertEqual and XCTAssertN…
nsalmoria May 12, 2016
00696ec
Merge branch 'sr-1417' of https://github.com/nsalmoria/swift-corelibs…
nsalmoria May 16, 2016
2ce4b57
Merge pull request #106 from linux-on-ibm-z/core-foundation-prefix
briancroom May 16, 2016
c65b335
Add non-throwing testCase() wrapper function.
ddunbar May 23, 2016
cf6b722
Merge pull request #116 from ddunbar/SR-1589
briancroom May 24, 2016
5b854aa
Take advantage of type inference when specifying `allTests` variables.
briancroom May 25, 2016
c82928c
Merge pull request #117 from briancroom/adjust-allTests
modocache May 25, 2016
3856ab5
[Tests] Set LD_LIBRARY_PATH when running tests
modocache May 26, 2016
4f7b21c
Merge pull request #118 from modocache/fix-pr-2609-gold-by-default
modocache May 26, 2016
05edf5f
NSBundles changes to rename mainBundle to main
SowmyaVikram May 27, 2016
4cb8f22
Add a command line flag for printing a list of the tests in the suite.
briancroom May 18, 2016
58fab00
Add a JSON output format for listing tests
briancroom May 20, 2016
ea21826
Include the new test listing mode in the documentation.
briancroom May 29, 2016
6be3a11
Include total count when listing tests
briancroom May 29, 2016
eb46e08
[build] Add an rpath of $ORIGIN.
ddunbar May 31, 2016
79f1fbd
Remove a long-deprecated build script flag.
briancroom May 31, 2016
b80b061
Merge pull request #120 from ddunbar/SR-1631
ddunbar May 31, 2016
b832308
Merge pull request #114 from briancroom/list-tests
modocache Jun 1, 2016
44e1ff7
Merge pull request #121 from briancroom/remove-deprecated-flag
briancroom Jun 3, 2016
446bc73
Merge branch 'NSBundleChanges' of https://github.com/SowmyaVikram/swi…
briancroom Jun 3, 2016
a856294
Separate public-facing and library-private source files
briancroom Jun 1, 2016
6bdeaf8
Merge pull request #122 from briancroom/rearrange-sources
modocache Jun 8, 2016
83cfdfe
[SR-1417] Add non-optional overloads of XCTAssertEqual and XCTAssertN…
nsalmoria May 12, 2016
82bc91d
[SR-1417] Add non-optional overloads of XCTAssertEqual and XCTAssertN…
nsalmoria May 12, 2016
05e475e
Merge branch 'sr-1417' of https://github.com/nsalmoria/swift-corelibs…
nsalmoria Jun 8, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 36 additions & 20 deletions Documentation/Linux.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,22 @@ When running on the Objective-C runtime, XCTest is able to find all of your test

```swift
class TestNSURL : XCTestCase {
static var allTests : [(String, (TestNSURL) -> () throws -> Void)] {
return [
("test_URLStrings", test_URLStrings),
("test_fileURLWithPath_relativeToURL", test_fileURLWithPath_relativeToURL),
("test_fileURLWithPath", test_fileURLWithPath),
("test_fileURLWithPath_isDirectory", test_fileURLWithPath_isDirectory),
// Other tests go here
]
}

func test_fileURLWithPath_relativeToURL() {
// Write your test here. Most of the XCTAssert macros you are familiar with are available.
XCTAssertTrue(theBestNumber == 42, "The number is wrong")
}

// Other tests go here
static var allTests = {
return [
("test_URLStrings", test_URLStrings),
("test_fileURLWithPath_relativeToURL", test_fileURLWithPath_relativeToURL),
("test_fileURLWithPath", test_fileURLWithPath),
("test_fileURLWithPath_isDirectory", test_fileURLWithPath_isDirectory),
// Other tests go here
]
}()

func test_fileURLWithPath_relativeToURL() {
// Write your test here. Most of the XCTAssert macros you are familiar with are available.
XCTAssertTrue(theBestNumber == 42, "The number is wrong")
}

// Other tests go here
}
```

Expand All @@ -29,11 +29,27 @@ Also, this version of XCTest does not use the external test runner binary. Inste
XCTMain([testCase(TestNSString.allTests), testCase(TestNSArray.allTests), testCase(TestNSDictionary.allTests)])
```

The `XCTMain` function does not return, and will cause your test app to exit with either `0` for success or `1` for failure. Command line arguments given to the executable can be used to select a particular test or test case to execute. For example:
We are currently investigating ideas on how to make these additional steps for test discovery automatic when running on the Swift runtime.

# Command Line Usage
The `XCTMain` function does not return, and will cause your test app to exit with either `0` for success or `1` for failure. Certain command line arguments can be used to modify the test runner behavior:

* A particular test or test case can be selected to execute. For example:

```sh
./FooTests FooTestCase/testFoo # Run a single test case
./FooTests FooTestCase # Run all the tests in FooTestCase
$ ./FooTests Tests.FooTestCase/testFoo # Run a single test case
$ ./FooTests Tests.FooTestCase # Run all the tests in FooTestCase
```
* Tests can be listed, instead of executed.

We are currently investigating ideas on how to make these additional steps for test discovery automatic when running on the Swift runtime.
```sh
$ ./FooTests --list-tests
Listing 4 tests in FooTests.xctest:

Tests.FooTestCase/testFoo
Tests.FooTestCase/testBar
Tests.BarTestCase/test123

$ ./FooTests --dump-tests-json
{"tests":[{"tests":[{"tests":[{"name":"testFoo"},{"name":"testBar"}],"name":"Tests.FooTestCase"},{"tests":[{"name":"test123"}],"name":"Tests.BarTestCase"}],"name":"Tests.xctest"}],"name":"All tests"}
```
File renamed without changes.
24 changes: 0 additions & 24 deletions Sources/XCTest/ArgumentParser.swift

This file was deleted.

65 changes: 65 additions & 0 deletions Sources/XCTest/Private/ArgumentParser.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//
// ArgumentParser.swift
// Tools for parsing test execution configuration from command line arguments.
//

/// Utility for converting command line arguments into a strongly-typed
/// representation of the passed-in options
internal struct ArgumentParser {

/// The basic operations that can be performed by an XCTest runner executable
enum ExecutionMode {
/// Run a test or test suite, printing results to stdout and exiting with
/// a non-0 return code if any tests failed. The name of a test or class
/// may be provided to only run a subset of test cases.
case run(selectedTestName: String?)

/// The different ways that the tests can be represented when they are listed
enum ListType {
/// A flat list of the tests that can be run. The lines in this
/// output are valid test names for the `run` mode.
case humanReadable

/// A JSON representation of the test suite, intended for consumption
/// by other tools
case json
}

/// Print a list of all the tests in the suite.
case list(type: ListType)

var selectedTestName: String? {
if case .run(let name) = self {
return name
} else {
return nil
}
}
}

private let arguments: [String]

init(arguments: [String] = Process.arguments) {
self.arguments = arguments
}

var executionMode: ExecutionMode {
if arguments.count <= 1 {
return .run(selectedTestName: nil)
} else if arguments[1] == "--list-tests" || arguments[1] == "-l" {
return .list(type: .humanReadable)
} else if arguments[1] == "--dump-tests-json" {
return .list(type: .json)
} else {
return .run(selectedTestName: arguments[1])
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ internal class PrintObserver: XCTestObservation {
}
}

extension PrintObserver: _XCTestObservation {
extension PrintObserver: XCTestInternalObservation {
func testCase(_ testCase: XCTestCase, didMeasurePerformanceResults results: String, file: StaticString, line: UInt) {
printAndFlush("\(file):\(line): Test Case '\(testCase.name)' measured \(results)")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ internal typealias TestFilter = (XCTestCase.Type, String) -> Bool
internal struct TestFiltering {
private let selectedTestName: String?

init(selectedTestName: String? = ArgumentParser().selectedTestName) {
init(selectedTestName: String?) {
self.selectedTestName = selectedTestName
}

Expand Down
107 changes: 107 additions & 0 deletions Sources/XCTest/Private/TestListing.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//
// TestListing.swift
// Implementation of the mode for printing the list of tests.
//

#if os(Linux) || os(FreeBSD)
import Foundation
#else
import SwiftFoundation
#endif

internal struct TestListing {
private let testSuite: XCTestSuite

init(testSuite: XCTestSuite) {
self.testSuite = testSuite
}

/// Prints a flat list of the tests in the suite, in the format used to
/// specify a test by name when running tests.
func printTestList() {
let list = testSuite.list()
let tests = list.count == 1 ? "test" : "tests"
let bundleName = testSuite.findBundleTestSuite()?.name ?? "<<unknown bundle>>"

print("Listing \(list.count) \(tests) in \(bundleName):\n")
for entry in testSuite.list() {
print(entry)
}
}

/// Prints a JSON representation of the tests in the suite, mirring the internal
/// tree representation of test suites and test cases. This output is intended
/// to be consumed by other tools.
func printTestJSON() {
let json = try! NSJSONSerialization.data(withJSONObject: testSuite.dictionaryRepresentation())
print(NSString(data: json, encoding: NSUTF8StringEncoding)!)
}
}

protocol Listable {
func list() -> [String]
func dictionaryRepresentation() -> NSDictionary
}

private func moduleName(value: Any) -> String {
let moduleAndType = String(reflecting: value.dynamicType)
return String(moduleAndType.characters.split(separator: ".").first!)
}

extension XCTestSuite: Listable {
private var listables: [Listable] {
return tests
.flatMap({ ($0 as? Listable) })
}

private var listingName: String {
if let childTestCase = tests.first as? XCTestCase where name == String(childTestCase.dynamicType) {
return "\(moduleName(value: childTestCase)).\(name)"
} else {
return name
}
}

func list() -> [String] {
return listables.flatMap({ $0.list() })
}

func dictionaryRepresentation() -> NSDictionary {
let listedTests = tests.flatMap({ ($0 as? Listable)?.dictionaryRepresentation() })
return [
"name": listingName.bridge(),
"tests": listedTests.bridge()
].bridge()
}

func findBundleTestSuite() -> XCTestSuite? {
if name.hasSuffix(".xctest") {
return self
} else {
return tests.flatMap({ ($0 as? XCTestSuite)?.findBundleTestSuite() }).first
}
}
}

extension XCTestCase: Listable {
func list() -> [String] {
let adjustedName = name.characters
.split(separator: ".")
.map(String.init)
.joined(separator: "/")
return ["\(moduleName(value: self)).\(adjustedName)"]
}

func dictionaryRepresentation() -> NSDictionary {
let methodName = String(name.characters.split(separator: ".").last!)
return ["name": methodName].bridge()
}
}
32 changes: 32 additions & 0 deletions Sources/XCTest/Private/XCTestInternalObservation.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//
// XCTestInternalObservation.swift
// Extra hooks used within XCTest for being notified about additional events
// during a test run.
//

/// Expanded version of `XCTestObservation` used internally to respond to
/// additional events not publicly exposed.
internal protocol XCTestInternalObservation: XCTestObservation {
/// Called when a test case finishes measuring performance and has results
/// to report
/// - Parameter testCase: The test case that did the measurements.
/// - Parameter results: The measured values and derived stats.
/// - Parameter file: The path to the source file where the failure was
/// reported, if available.
/// - Parameter line: The line number in the source file where the failure
/// was reported.
func testCase(_ testCase: XCTestCase, didMeasurePerformanceResults results: String, file: StaticString, line: UInt)
}

// All `XCInternalTestObservation` methods are optional, so empty default implementations are provided
internal extension XCTestInternalObservation {
func testCase(_ testCase: XCTestCase, didMeasurePerformanceResults results: String, file: StaticString, line: UInt) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,17 @@ public func XCTAssert(_ expression: @autoclosure () throws -> Boolean, _ message
XCTAssertTrue(expression, message, file: file, line: line)
}

public func XCTAssertEqual<T: Equatable>(_ expression1: @autoclosure () throws -> T, _ expression2: @autoclosure () throws -> T, _ message: @autoclosure () -> String = "", file: StaticString = #file, line: UInt = #line) {
_XCTEvaluateAssertion(.equal, message: message, file: file, line: line) {
let (value1, value2) = (try expression1(), try expression2())
if value1 == value2 {
return .success
} else {
return .expectedFailure("(\"\(value1)\") is not equal to (\"\(value2)\")")
}
}
}

public func XCTAssertEqual<T: Equatable>(_ expression1: @autoclosure () throws -> T?, _ expression2: @autoclosure () throws -> T?, _ message: @autoclosure () -> String = "", file: StaticString = #file, line: UInt = #line) {
_XCTEvaluateAssertion(.equal, message: message, file: file, line: line) {
let (value1, value2) = (try expression1(), try expression2())
Expand Down Expand Up @@ -288,6 +299,17 @@ public func XCTAssertNil(_ expression: @autoclosure () throws -> Any?, _ message
}
}

public func XCTAssertNotEqual<T: Equatable>(_ expression1: @autoclosure () throws -> T, _ expression2: @autoclosure () throws -> T, _ message: @autoclosure () -> String = "", file: StaticString = #file, line: UInt = #line) {
_XCTEvaluateAssertion(.notEqual, message: message, file: file, line: line) {
let (value1, value2) = (try expression1(), try expression2())
if value1 != value2 {
return .success
} else {
return .expectedFailure("(\"\(value1)\") is equal to (\"\(value2)\")")
}
}
}

public func XCTAssertNotEqual<T: Equatable>(_ expression1: @autoclosure () throws -> T?, _ expression2: @autoclosure () throws -> T?, _ message: @autoclosure () -> String = "", file: StaticString = #file, line: UInt = #line) {
_XCTEvaluateAssertion(.notEqual, message: message, file: file, line: line) {
let (value1, value2) = (try expression1(), try expression2())
Expand Down
Loading