Commit 0947a014 authored by Drew's avatar Drew

Adding "xctestStrict", a mode that enforces strict XCTest requirements

parent 1746ab18
Pipeline #745 passed with stage
...@@ -23,6 +23,56 @@ import atpkg ...@@ -23,6 +23,56 @@ import atpkg
For more information on this tool, see `docs/attllbuild.md` */ For more information on this tool, see `docs/attllbuild.md` */
final class ATllbuild : Tool { final class ATllbuild : Tool {
/**We inject this sourcefile in xctestify=true on OSX
On Linux, the API requires you to explicitly list tests
which is not required on OSX. Injecting this file into test targets
will enforce that API on OSX as well */
private static let xcTestCaseProvider: String = { () -> String in
var s = ""
s += "import XCTest\n"
s += "\n"
s += "protocol XCTestCaseProvider {\n"
s += " var allTests : [(String, () -> Void)] { get }\n"
s += "}\n"
s += "\n"
s += "public func XCTMain(testCases: [XCTestCase]) {\n"
s += " fatalError(\"Can't get here.\")\n"
s += "}\n"
s += "\n"
s += "extension XCTestCase {\n"
s += " private func implementAllTests() {\n"
s += " print(\"Make sure to implement allTests via\")\n"
s += " print(\"extension \\(self.dynamicType) : XCTestCaseProvider {\")\n"
s += " print(\" var allTests : [(String, () -> Void)] {\")\n"
s += " print(\" return [\")\n"
s += " print(\" (\\\"testFoo\\\", testFoo)\")\n"
s += " print(\" )]\")\n"
s += " print(\" }\")\n"
s += " print(\"}\")\n"
s += " print(\"(Or disable xctestStrict.)\")\n"
s += " print(\"Cheers! -- Anarchy Tools Team\")\n"
s += " }\n"
s += " override public func tearDown() {\n"
s += " if let provider = self as? XCTestCaseProvider {\n"
s += " let contains = provider.allTests.contains({ test in\n"
s += " return test.0 == invocation!.selector.description\n"
s += " })\n"
s += " if !contains {\n"
s += " XCTFail(\"Test \\(name) is missing from \\(self.dynamicType)\")\n"
s += " implementAllTests()\n"
s += " }\n"
s += " }\n"
s += " else {\n"
s += " XCTFail(\"Whoops! \\(self.dynamicType) doesn't conform to XCTestCaseProvider.\")\n"
s += " implementAllTests()\n"
s += " }\n"
s += " super.tearDown()\n"
s += " }\n"
s += "}\n"
s += "\n"
return s
}()
enum OutputType { enum OutputType {
case Executable case Executable
case StaticLibrary case StaticLibrary
...@@ -182,18 +232,29 @@ final class ATllbuild : Tool { ...@@ -182,18 +232,29 @@ final class ATllbuild : Tool {
} }
} }
guard let sourceDescriptions = task["source"]?.vector?.flatMap({$0.string}) else { fatalError("Can't find sources for atllbuild.") }
var sources = collectSources(sourceDescriptions, task: task)
//xctestify //xctestify
if task["xctestify"]?.bool == true { if task["xctestify"]?.bool == true {
precondition(outputType == .Executable, "You must use outputType: executable with xctestify.") precondition(outputType == .Executable, "You must use outputType: executable with xctestify.")
//inject platform-specific flags //inject platform-specific flags
#if os(OSX) #if os(OSX)
compileOptions.appendContentsOf(["-F", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks/"]) compileOptions.appendContentsOf(["-F", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks/"])
linkOptions.appendContentsOf(["-F", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks/", "-target", "x86_64-apple-macosx10.11", "-Xlinker", "-rpath", "-Xlinker", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks/", "-Xlinker", "-bundle"]) linkOptions.appendContentsOf(["-F", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks/", "-target", "x86_64-apple-macosx10.11", "-Xlinker", "-rpath", "-Xlinker", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks/", "-Xlinker", "-bundle"])
#endif
}
if task["xctestStrict"]?.bool == true {
#if os(OSX)
//inject XCTestCaseProvider.swift
var xcTestCaseProviderPath = "/tmp/XXXXXXX"
var template = xcTestCaseProviderPath.cStringUsingEncoding(NSUTF8StringEncoding)!
xcTestCaseProviderPath = String(CString: mkdtemp(&template), encoding: NSUTF8StringEncoding)!
xcTestCaseProviderPath += "/XCTestCaseProvider.swift"
try! ATllbuild.xcTestCaseProvider.writeToFile(xcTestCaseProviderPath, atomically: false, encoding: NSUTF8StringEncoding)
sources.append(xcTestCaseProviderPath)
#endif #endif
} }
guard let sourceDescriptions = task["source"]?.vector?.flatMap({$0.string}) else { fatalError("Can't find sources for atllbuild.") }
let sources = collectSources(sourceDescriptions, task: task)
guard let name = task["name"]?.string else { fatalError("No name for atllbuild task") } guard let name = task["name"]?.string else { fatalError("No name for atllbuild task") }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
:name "footests" :name "footests"
:dependencies ["build-lib"] :dependencies ["build-lib"]
:xctestify true :xctestify true
:xctestStrict true
:linkWithProduct["Foo.a"] :linkWithProduct["Foo.a"]
} }
:run-tests { :run-tests {
......
...@@ -15,12 +15,15 @@ ...@@ -15,12 +15,15 @@
import XCTest import XCTest
class FooTests: XCTestCase { class FooTests: XCTestCase {
func testFoo() {
XCTAssert(Foo().whatever() == 12)
}
}
extension FooTests: XCTestCaseProvider {
var allTests : [(String, () -> Void)] { var allTests : [(String, () -> Void)] {
return [ return [
("testFoo", testFoo) ("testFoo", testFoo)
] ]
} }
func testFoo() {
XCTAssert(Foo().whatever() == 12)
}
} }
\ No newline at end of file
(package
:name "xcs"
:tasks {
:build-lib {
:tool "atllbuild"
:source ["src/**.swift"]
:outputType "static-library"
:name "Foo"
:compileOptions ["-enable-testing"]
}
:build-tests {
:tool "atllbuild"
:source ["test/**.swift"]
:outputType "executable"
:name "footests"
:dependencies ["build-lib"]
:xctestify true
:xctestStrict true
:linkWithProduct["Foo.a"]
}
:run-tests {
:tool "xctestrun"
:testExecutable ".atllbuild/products/footests"
:dependencies ["build-tests"]
}
}
)
\ No newline at end of file
// Copyright (c) 2016 Anarchy Tools Contributors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
class Foo {
func whatever() -> Int {
return 12
}
}
\ No newline at end of file
// Copyright (c) 2016 Anarchy Tools Contributors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
@testable import Foo
import XCTest
class FooTests: XCTestCase {
func testFoo() {
XCTAssert(Foo().whatever() == 12)
}
}
extension FooTests: XCTestCaseProvider {
var allTests : [(String, () -> Void)] {
return [
//("testFoo", testFoo) oops! Forgot this one!
]
}
}
\ No newline at end of file
// Copyright (c) 2016 Anarchy Tools Contributors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import XCTest
XCTMain([FooTests()])
\ No newline at end of file
(package
:name "xcs"
:tasks {
:build-lib {
:tool "atllbuild"
:source ["src/**.swift"]
:outputType "static-library"
:name "Foo"
:compileOptions ["-enable-testing"]
}
:build-tests {
:tool "atllbuild"
:source ["test/**.swift"]
:outputType "executable"
:name "footests"
:dependencies ["build-lib"]
:xctestify true
:xctestStrict true
:linkWithProduct["Foo.a"]
}
:run-tests {
:tool "xctestrun"
:testExecutable ".atllbuild/products/footests"
:dependencies ["build-tests"]
}
}
)
\ No newline at end of file
// Copyright (c) 2016 Anarchy Tools Contributors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
class Foo {
func whatever() -> Int {
return 12
}
}
\ No newline at end of file
// Copyright (c) 2016 Anarchy Tools Contributors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
@testable import Foo
import XCTest
class FooTests: XCTestCase {
func testFoo() {
XCTAssert(Foo().whatever() == 12)
}
}
\ No newline at end of file
// Copyright (c) 2016 Anarchy Tools Contributors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import XCTest
XCTMain([FooTests()])
\ No newline at end of file
...@@ -3,6 +3,7 @@ set -e ...@@ -3,6 +3,7 @@ set -e
echo "**********THE ATBUILD TEST SCRIPT*************" echo "**********THE ATBUILD TEST SCRIPT*************"
DIR=`pwd`
ATBUILD="`pwd`/.atllbuild/products/atbuild" ATBUILD="`pwd`/.atllbuild/products/atbuild"
pwd pwd
...@@ -12,4 +13,25 @@ $ATBUILD atbuild ...@@ -12,4 +13,25 @@ $ATBUILD atbuild
echo "*****************XCS TEST**********************" echo "*****************XCS TEST**********************"
cd tests/fixtures/xcs && $ATBUILD run-tests cd tests/fixtures/xcs && $ATBUILD run-tests
echo "*****************STRICT CHECKS**********************"
if [ `uname` != "Darwin" ]; then
echo "Not checking STRICT for non-Darwin platform"
else
cd $DIR/tests/fixtures/xcs_strict
if $ATBUILD run-tests; then
echo "Expected a failure in xcs_strict"
exit 1
else
echo "Strict failed as expected"
fi
cd $DIR/tests/fixtures/xcs_strict_2
if $ATBUILD run-tests; then
echo "Expected a failure in xcs_strict"
exit 1
else
echo "Strict failed as expected"
fi
fi
echo "***ATBUILD TEST SCRIPT PASSED SUCCESSFULLY*****" echo "***ATBUILD TEST SCRIPT PASSED SUCCESSFULLY*****"
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment