-
-
Save kapoorlakshya/8c0020b3058e56013b71c0274c81120a to your computer and use it in GitHub Desktop.
Sample for pushing XCTest/XCUITest results to TestRail
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// TestRailObservation.swift | |
// | |
import Foundation | |
import XCTest | |
class TestRailObservation: NSObject, XCTestObservation { | |
// Add a user / pass or key for testrail generation | |
var testrailUsername: String = "" | |
var testrailKey: String = "" | |
var testRun: Int? = nil | |
var testResults: [Result] = [] | |
var title: String { get { return "iPhone iOS Ticketing Regression" } } | |
struct Result: Encodable { | |
var case_id: Int | |
var status_id: Int | |
var comment: String? | |
} | |
struct Results: Encodable { | |
var results: [Result] | |
} | |
struct TestrailResponse: Decodable { | |
var id: Int | |
var url: String | |
} | |
override init() { | |
super.init() | |
XCTestObservationCenter.shared.addTestObserver(self) | |
} | |
func testCaseDidFinish(_ testCase: XCTestCase) { | |
for id in self.parseTestCases(name: testCase.name) { | |
if (!self.testResults.contains(where: {$0.case_id == id})) { | |
testResults.append(Result(case_id: id, status_id: 1, comment: nil)) | |
} | |
} | |
} | |
func testCase(_ testCase: XCTestCase, didRecord issue: XCTIssue) { | |
for id in self.parseTestCases(name: testCase.name) { | |
self.testResults.append(Result(case_id: id, status_id: 5, comment: issue.description)) | |
} | |
} | |
private func parseTestCases(name: String) -> [Int] { | |
var testCaseIds: [Int] = [] | |
let substrings = name.components(separatedBy: "_") | |
for substring in substrings { | |
if (substring.range(of: "^C\\d+$", options: .regularExpression) != nil) { | |
let testCaseId = Int(substring.dropFirst())! | |
testCaseIds.append(testCaseId) | |
} | |
} | |
return testCaseIds | |
} | |
private func createRequest(url: String) -> URLRequest { | |
let auth = String(format: "%@:%@", testrailUsername, testrailKey).data(using: String.Encoding.utf8)!.base64EncodedString() | |
var request = URLRequest(url: URL(string: url)!) | |
request.httpMethod = "POST" | |
request.setValue("Basic \(auth)", forHTTPHeaderField: "Authorization") | |
request.setValue("application/json", forHTTPHeaderField: "Content-Type") | |
return request | |
} | |
// This method provides a customization point for any post-testing activity. The test process will generally exit after this method returns, so if there is long running and/or asynchronous work to be done after testing, be sure to implement this method in a way that blocks until all long running activity is complete. | |
// -https://developer.apple.com/documentation/xctest/xctestobservation/1500819-testbundledidfinish | |
func testBundleDidFinish(_ testBundle: Bundle) { | |
self.testrailUsername = ProcessInfo.processInfo.environment["TESTRAIL_USERNAME"] ?? "" | |
self.testrailKey = ProcessInfo.processInfo.environment["TESTRAIL_KEY"] ?? "" | |
if (self.testrailUsername != "" && self.testrailKey != "") { | |
let semaphore = DispatchSemaphore(value: 0) | |
var addRunRequest = createRequest(url: "https://example.testrail.com/index.php?/api/v2/add_run/1") | |
addRunRequest.httpBody = Data("{\"suite_id\":1,\"name\":\"\(self.title)\"}".utf8) | |
let addRunTask = URLSession.shared.dataTask(with: addRunRequest) {(data, response, error) in | |
guard let data = data else { return } | |
do { | |
let addRunResult = try JSONDecoder().decode(TestrailResponse.self, from: data) | |
let testRun = addRunResult.id | |
let encoder = JSONEncoder() | |
let results = Results(results: self.testResults) | |
let encodedArray = try! encoder.encode(results) | |
var addResultsRequest = self.createRequest(url: "https://example.testrail.com/index.php?/api/v2/add_results_for_cases/\(testRun)") | |
addResultsRequest.httpBody = Data(encodedArray) | |
let addResultsTask = URLSession.shared.dataTask(with: addResultsRequest) {(data, response, error) in | |
semaphore.signal() | |
} | |
addResultsTask.resume() | |
} catch { | |
print(error) | |
} | |
} | |
addRunTask.resume() | |
semaphore.wait() | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment