From f788f8a3de3724317dccaa716670fd5e84aa8cdf Mon Sep 17 00:00:00 2001 From: Mihai Seremet Date: Thu, 22 Dec 2016 23:25:10 +0200 Subject: [PATCH] Handle reporters with absolute path as output path Slightly refactored reporter coordinators --- .../temper/Output/JSONCoordinator.swift | 41 +++-- .../temper/Output/OutputCoordinator.swift | 10 +- .../temper/Output/PLAINCoordinator.swift | 8 +- .../temper/Output/PMDCoordinator.swift | 64 ++++--- TaylorFramework/Resources/Help.txt | 11 +- .../TemperTests/NSFileManagerTests.swift | 24 ++- .../TemperTests/OutputCoordinatorTests.swift | 170 ++++++++---------- .../TemperTests/TemperTests.swift | 65 +++---- .../ReporterComparator.swift | 9 +- .../TaylorIntegrationTests.swift | 54 ++++-- 10 files changed, 263 insertions(+), 193 deletions(-) diff --git a/TaylorFramework/Modules/temper/Output/JSONCoordinator.swift b/TaylorFramework/Modules/temper/Output/JSONCoordinator.swift index 46c2978..a073555 100644 --- a/TaylorFramework/Modules/temper/Output/JSONCoordinator.swift +++ b/TaylorFramework/Modules/temper/Output/JSONCoordinator.swift @@ -8,35 +8,46 @@ import Foundation +private typealias JSON = [String:[[String:AnyObject]]] + struct JSONCoordinator: WritingCoordinator { func writeViolations(_ violations: [Violation], atPath path: String) { FileManager().removeFileAtPath(path) - let json = generateJSON(violations) - var jsonData: Data? = nil - do { - jsonData = try JSONSerialization.data(withJSONObject: json, options: JSONSerialization.WritingOptions.prettyPrinted) - } catch { - print("Error while creating the JSON object.") - } do { - try jsonData?.write(to: URL(fileURLWithPath: path), options: NSData.WritingOptions.withoutOverwriting) - } catch { - print("Error while writing the JSON object to file.") + let json = generateJSON(from: violations) + let data = try generateData(from: json) + try write(data: data, at: path) + } catch let error { + let message = "Error while creating JSON report." + "\n" + + "Reason: " + error.localizedDescription + Printer(verbosityLevel: .error).printError(message) } } - fileprivate func generateJSON(_ violations: [Violation]) -> [String:[[String:AnyObject]]] { + private func generateJSON(from violations: [Violation]) -> JSON { return ["violation" : violations.map() { $0.toDictionary() }] - } + } + + private func generateData(from json: JSON) throws -> Data { + return try JSONSerialization.data(withJSONObject: json, options: .prettyPrinted) + } + + private func write(data: Data, at path: String) throws { + try data.write(to: URL(fileURLWithPath: path), options: .atomic) + } } extension FileManager { func removeFileAtPath(_ path: String) { var isDirectory: ObjCBool = false - if !FileManager.default.fileExists(atPath: path, isDirectory: &isDirectory) && !isDirectory.boolValue { return } + guard fileExists(atPath: path, isDirectory: &isDirectory) && !isDirectory.boolValue else { return } do { - try FileManager.default.removeItem(atPath: path) - } catch { print("Error while removing item at path: \(path)") } + try removeItem(atPath: path) + } catch let error { + let message = "Error while removing file at path: " + path + "\n" + + "Reason: " + error.localizedDescription + Printer(verbosityLevel: .error).printError(message) + } } } diff --git a/TaylorFramework/Modules/temper/Output/OutputCoordinator.swift b/TaylorFramework/Modules/temper/Output/OutputCoordinator.swift index 1414ab3..c7dfe29 100644 --- a/TaylorFramework/Modules/temper/Output/OutputCoordinator.swift +++ b/TaylorFramework/Modules/temper/Output/OutputCoordinator.swift @@ -19,11 +19,15 @@ final class OutputCoordinator { func writeTheOutput(_ violations: [Violation], reporters: [Reporter]) { self.reporters = reporters for reporter in reporters { - if reporter.fileName.isEmpty && (reporter.concreteReporter as? XcodeReporter) == nil { continue } - let path = (filePath as NSString).appendingPathComponent(reporter.fileName) - reporter.coordinator().writeViolations(violations, atPath: path) + write(violations: violations, with: reporter) } } + + private func write(violations: [Violation], with reporter: Reporter) { + if reporter.fileName.isEmpty && (reporter.concreteReporter as? XcodeReporter) == nil { return } + let outputPath = reporter.fileName.absolutePath(filePath) + reporter.coordinator().writeViolations(violations, atPath: outputPath) + } } protocol WritingCoordinator { diff --git a/TaylorFramework/Modules/temper/Output/PLAINCoordinator.swift b/TaylorFramework/Modules/temper/Output/PLAINCoordinator.swift index 408b4ba..ef43ab5 100644 --- a/TaylorFramework/Modules/temper/Output/PLAINCoordinator.swift +++ b/TaylorFramework/Modules/temper/Output/PLAINCoordinator.swift @@ -13,9 +13,11 @@ final class PLAINCoordinator: WritingCoordinator { FileManager().removeFileAtPath(path) let content = generateFileContentFromViolations(violations) do { - try content.write(toFile: path, atomically: true, encoding: String.Encoding.utf8) - } catch _ { - print("Error while trying to write the content of string in file.") + try content.write(toFile: path, atomically: true, encoding: .utf8) + } catch let error { + let message = "Error while writing content of string at path: " + path + "\n" + + "Reason: " + error.localizedDescription + Printer(verbosityLevel: .error).printError(message) } } diff --git a/TaylorFramework/Modules/temper/Output/PMDCoordinator.swift b/TaylorFramework/Modules/temper/Output/PMDCoordinator.swift index 50e74b6..d98fa26 100644 --- a/TaylorFramework/Modules/temper/Output/PMDCoordinator.swift +++ b/TaylorFramework/Modules/temper/Output/PMDCoordinator.swift @@ -8,43 +8,65 @@ import Foundation +private typealias ViolationsMap = [Path: [Violation]] + final class PMDCoordinator: WritingCoordinator { func writeViolations(_ violations: [Violation], atPath path: String) { FileManager().removeFileAtPath(path) - let xml = generateXML(violations) + let map = mapViolations(violations) + let xml = generateXML(from: map) let xmlData = xml.xmlData(withOptions: Int(XMLNode.Options.nodePrettyPrint.rawValue)) do { - try xmlData.write(to: URL(fileURLWithPath: path), options: NSData.WritingOptions.withoutOverwriting) - } catch { - print("Error while writing the XML object to file.") + try xmlData.write(to: URL(fileURLWithPath: path), options: .atomic) + } catch let error { + let message = "Error while creating PMD report." + "\n" + + "Reason: " + error.localizedDescription + Printer(verbosityLevel: .error).printError(message) + } + } + + private func mapViolations(_ violations: [Violation]) -> ViolationsMap { + return violations.reduce([Path : [Violation]]()) { result, violation in + let path = violation.path + + // Add violation to the group with the same path + var violations = result[path] ?? [] + violations.append(violation) + + // Update the result + var nextResult = result + nextResult[path] = violations + + return nextResult } } - fileprivate func generateXML(_ violations: [Violation]) -> XMLDocument { + private func generateXML(from violationsMap: ViolationsMap) -> XMLDocument { let xml = XMLDocument(rootElement: XMLElement(name: "pmd")) xml.version = "1.0" xml.characterEncoding = "UTF-8" - addElementsToXML(xml, fromViolations: violations) + + let fileElements = violationsMap.map(generateFileElement) + xml.rootElement()?.addChildren(fileElements) + return xml } - fileprivate func addElementsToXML(_ xml: XMLDocument, fromViolations violations: [Violation]) { - for filePath in filePathsFromViolations(violations) { - let fileElement = XMLElement(name: "file") - let attributeNode = XMLNode.attribute(withName: "name", stringValue: filePath) as? XMLNode - guard let attribute = attributeNode else { - return - } - fileElement.addAttribute(attribute) - let _ = violations.filter({ $0.path == filePath }).map({ fileElement.addChild($0.toXMLElement()) }) - if let root = xml.rootElement() { - root.addChild(fileElement) - } + private func generateFileElement(path: Path, violations: [Violation]) -> XMLElement { + let element = XMLElement(name: "file") + if let attribute = XMLNode.attribute(withName: "name", stringValue: path) as? XMLNode { + element.addAttribute(attribute) } + + violations.forEach { element.addChild($0.toXMLElement()) } + + return element } - - fileprivate func filePathsFromViolations(_ violations: [Violation]) -> [String] { - return violations.map({ $0.path }).unique +} + +extension XMLElement { + func addChildren(_ children: [XMLElement]) { + children.forEach(addChild) } } diff --git a/TaylorFramework/Resources/Help.txt b/TaylorFramework/Resources/Help.txt index 13adb5c..3da6e86 100644 --- a/TaylorFramework/Resources/Help.txt +++ b/TaylorFramework/Resources/Help.txt @@ -21,10 +21,13 @@ options: Path to recursive analyse (default current path). Must be maximum one path option - -r, --reporter type:file_name - Saves report in file with given "file_name" and "type" at analyze path. - Each "type" must be indicated no more than one time. - Supported types : json, pmd, plain, xcode(without path). + -r, --reporter type:output_path + Types of reports to be created after analyzing. + Currently we support "json", "pmd", "plain" and "xcode" (without "output_path") types or reports. + Each "type" must be indicated only once. + "output_path" can be a relative path to analyze path, see -p/--path option, + or an absolute path, and should also contain reporter name. + E.g: "-r json:report.json" or "-r pmd:~/Desktop/Taylor/report.pmd" -rc, --ruleCustomization rule=value Rules for code analisys. diff --git a/TaylorFrameworkTests/TemperTests/NSFileManagerTests.swift b/TaylorFrameworkTests/TemperTests/NSFileManagerTests.swift index 60ee165..56c2d89 100644 --- a/TaylorFrameworkTests/TemperTests/NSFileManagerTests.swift +++ b/TaylorFrameworkTests/TemperTests/NSFileManagerTests.swift @@ -11,6 +11,16 @@ import Nimble import Quick @testable import TaylorFramework +fileprivate final class MockFileManagerNotRemovable: FileManager { + enum FileManagerError: Error { + case notRemovable + } + + override func removeItem(atPath path: String) throws { + throw FileManagerError.notRemovable + } +} + class NSFileManagerTests: QuickSpec { override func spec() { describe("NSFileManager") { @@ -26,7 +36,19 @@ class NSFileManagerTests: QuickSpec { manager.removeFileAtPath(filePath) expect(manager.fileExists(atPath: filePath)).to(beFalse()) } - it("should't remove directory at path") { + + it("shouldn't remove file at path if it's not removable") { + let manager = MockFileManagerNotRemovable() + let path = manager.currentDirectoryPath as NSString + let filePath = path.appendingPathComponent("file.txt") as String + manager.createFile(atPath: filePath, contents: nil, attributes: nil) + expect(manager.fileExists(atPath: filePath)).to(beTrue()) + manager.removeFileAtPath(filePath) + expect(manager.fileExists(atPath: filePath)).to(beTrue()) + FileManager.default.removeFileAtPath(filePath) + } + + it("shouldn't remove directory at path") { let manager = FileManager.default expect(manager.fileExists(atPath: manager.currentDirectoryPath)).to(beTrue()) if manager.fileExists(atPath: (manager.currentDirectoryPath as NSString).appendingPathComponent("blablabla")) { diff --git a/TaylorFrameworkTests/TemperTests/OutputCoordinatorTests.swift b/TaylorFrameworkTests/TemperTests/OutputCoordinatorTests.swift index 8477541..395094a 100644 --- a/TaylorFrameworkTests/TemperTests/OutputCoordinatorTests.swift +++ b/TaylorFrameworkTests/TemperTests/OutputCoordinatorTests.swift @@ -11,128 +11,108 @@ import Quick @testable import TaylorFramework class OutputCoordinatorTests : QuickSpec { - let helper : TestsHelper = TestsHelper() - lazy var reporterPath : String = { - let folderPath = (NSHomeDirectory() as NSString).appendingPathComponent("TemperTestsTempFiles") - do { - if FileManager.default.fileExists(atPath: folderPath) { return folderPath } - try FileManager.default.createDirectory(atPath: folderPath, withIntermediateDirectories: false, attributes: nil) - } catch _ { - return NSHomeDirectory() - } - - return folderPath - }() + let helper: TestsHelper = TestsHelper() override func spec() { describe("Output Coordinator") { - func removeFileAtPaths(_ paths: [String]) { - for path in paths { - FileManager().removeFileAtPath(path) - } - } - afterEach { - let path = FileManager.default.currentDirectoryPath as NSString - let jsonPath = path.appendingPathComponent(JSONReporter().defaultFileName()) - let pmdPath = path.appendingPathComponent(PMDReporter().defaultFileName()) - let plainPath = path.appendingPathComponent(PlainReporter().defaultFileName()) - removeFileAtPaths([jsonPath, pmdPath, plainPath, self.reporterPath]) - } it("should write the violations in JSON file") { - let aComponent = TestsHelper().aComponent - let aRule = TestsHelper().aRule - let violation = Violation(component: aComponent, rule: aRule, violationData: ViolationData(message: "msg", path: "path", value: 100)) - let filePath = (self.reporterPath as NSString).appendingPathComponent(JSONReporter().defaultFileName()) - OutputCoordinator(filePath: self.reporterPath).writeTheOutput([violation], reporters: [Reporter(JSONReporter())]) - let jsonData = try? Data(contentsOf: URL(string: filePath)!) - var jsonResult : NSDictionary? = nil - guard let data = jsonData else { - return - } - do { - jsonResult = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary - } catch { - print("Error while creating the JSON object.") - } - guard let result = jsonResult else { - return - } - if let violations = result["violation"] as? [Dictionary] { - if let violationDictionary = violations.first { - expect(violation.message).to(equal(violationDictionary["message"] as? String)) - expect(violation.rule.rule).to(equal(violationDictionary["rule"] as? String)) - expect(violation.path).to(equal(violationDictionary["path"] as? String)) - expect(violation.value).to(equal(violationDictionary["value"] as? Int)) - expect(violation.rule.externalInfoUrl).to(equal(violationDictionary["externalInfoUrl"] as? String)) - expect(violation.component.name).to(equal(violationDictionary["class"] as? String)) - expect(violation.component.range).to(equal(ComponentRange.deserialize(violationDictionary))) - } - } - let path = "trololo" - OutputCoordinator(filePath: path).writeTheOutput([violation], reporters: [Reporter(JSONReporter())]) - expect(FileManager.default.fileExists(atPath: path)).to(beFalse()) + let violation = Violation(component: TestsHelper().aComponent, + rule: TestsHelper().aRule, + violationData: ViolationData(message: "msg", path: "path", value: 100)) + + // Create report + let filePath = (NSHomeDirectory() as NSString).appendingPathComponent(JSONReporter().defaultFileName()) + OutputCoordinator(filePath: NSHomeDirectory()).writeTheOutput([violation], reporters: [Reporter(JSONReporter())]) + + // Read report + guard let content = try? String(contentsOfFile: filePath) else { return fail() } + guard let data = content.data(using: .utf8) else { return fail() } + guard let jsonResult = try? JSONSerialization.jsonObject(with: data, + options: JSONSerialization.ReadingOptions.mutableContainers) + as? [String: AnyObject] else { return fail() } + guard let result = jsonResult else { return fail() } + guard let violations = result["violation"] as? [[String: AnyObject]] else { return fail() } + guard let violationDictionary = violations.first else { return fail() } + + // Check report + expect(violation.message).to(equal(violationDictionary["message"] as? String)) + expect(violation.rule.rule).to(equal(violationDictionary["rule"] as? String)) + expect(violation.path).to(equal(violationDictionary["path"] as? String)) + expect(violation.value).to(equal(violationDictionary["value"] as? Int)) + expect(violation.rule.externalInfoUrl).to(equal(violationDictionary["externalInfoUrl"] as? String)) + expect(violation.component.name).to(equal(violationDictionary["class"] as? String)) + expect(violation.component.range).to(equal(ComponentRange.deserialize(violationDictionary))) + + // Cleanup + FileManager.default.removeFileAtPath(filePath) } it("should write the violations in XML file") { let aComponent = TestsHelper().aComponent let aRule = TestsHelper().aRule let component = aComponent - let childComponent = component.makeComponent(type: ComponentType.function, range: ComponentRange(sl: 10, el: 30), name: "justFunction") - let violation = Violation(component: childComponent, rule: aRule, violationData: ViolationData(message: "msg", path: "path", value: 100)) - let filePath = (self.reporterPath as NSString).appendingPathComponent(PMDReporter().defaultFileName()) - OutputCoordinator(filePath: self.reporterPath).writeTheOutput([violation], reporters: [Reporter(PMDReporter())]) - let xmlData = try? Data(contentsOf: URL(string: filePath)!) - guard let data = xmlData else { - return - } - var xml : XMLDocument? = nil - do { - xml = try XMLDocument(data: data, options: 0) - } catch { - print("Error while redaing from XML file.") - } - guard let result = xml else { - return - } - guard let root = result.rootElement() else { - return - } + let childComponent = component.makeComponent(type: ComponentType.function, + range: ComponentRange(sl: 10, el: 30), + name: "justFunction") + let violation = Violation(component: childComponent, + rule: aRule, + violationData: ViolationData(message: "msg", path: "path", value: 100)) + + // Create report + let filePath = (NSHomeDirectory() as NSString).appendingPathComponent(PMDReporter().defaultFileName()) + OutputCoordinator(filePath: NSHomeDirectory()).writeTheOutput([violation], reporters: [Reporter(PMDReporter())]) + + // Read report + guard let content = try? String(contentsOfFile: filePath) else { return fail() } + guard let xml = try? XMLDocument(xmlString: content, options: 0) else { return fail() } + guard let root = xml.rootElement() else { return fail() } + + // Check report expect(root.name).to(equal("pmd")) - let fileElement = root.elements(forName: "file").first - expect(fileElement?.attribute(forName: "name")?.stringValue).to(equal("path")) - let violationElement = fileElement?.elements(forName: "violation").first - expect(violationElement?.stringValue).to(equal("msg")) + + let fileElement = root.elements(forName: "file").first! + expect(fileElement.attribute(forName: "name")?.stringValue).to(equal("path")) + + let violationElement = fileElement.elements(forName: "violation").first! + expect(violationElement.stringValue).to(equal("msg")) + let element = violation.toXMLElement() - let violationAttributes = violationElement?.attributes + let violationAttributes = violationElement.attributes let elementAttributes = element.attributes expect(violationAttributes).to(equal(elementAttributes)) + + // Cleanup + FileManager.default.removeFileAtPath(filePath) + } + it("shouldn't create report when give a wrong path") { + let violation = Violation(component: TestsHelper().aComponent, + rule: TestsHelper().aRule, + violationData: ViolationData(message: "msg", path: "path", value: 100)) let path = "trololo" OutputCoordinator(filePath: path).writeTheOutput([violation], reporters: [Reporter(PMDReporter())]) expect(FileManager.default.fileExists(atPath: path)).to(beFalse()) + OutputCoordinator(filePath: path).writeTheOutput([violation], reporters: [Reporter(JSONReporter())]) + expect(FileManager.default.fileExists(atPath: path)).to(beFalse()) } it("should write the violations in TXT file") { let aComponent = TestsHelper().aComponent - var folderPath = (NSHomeDirectory() as NSString).appendingPathComponent("TemperTestsTempFiles") - do { - if !FileManager.default.fileExists(atPath: folderPath) { - try FileManager.default.createDirectory(atPath: folderPath, withIntermediateDirectories: false, attributes: nil) - } - } catch _ { - folderPath = NSHomeDirectory() - } - let filePath = (folderPath as NSString).appendingPathComponent(PlainReporter().defaultFileName()) + let filePath = (NSHomeDirectory() as NSString).appendingPathComponent(PlainReporter().defaultFileName()) let fileContent = FileContent(path: "path", components: [aComponent, aComponent, aComponent, aComponent, aComponent]) let reporter = PlainReporter() - let temper = Temper(outputPath: folderPath) + let temper = Temper(outputPath: NSHomeDirectory()) temper.setReporters([Reporter(reporter)]) temper.checkContent(fileContent) temper.finishTempering() expect(FileManager.default.fileExists(atPath: filePath)).to(beTrue()) let path = "trololo" - let violation = Violation(component: aComponent, rule: NestedBlockDepthRule(), violationData: ViolationData(message: "msg", path: "path", value: 100)) + let violation = Violation(component: aComponent, + rule: NestedBlockDepthRule(), + violationData: ViolationData(message: "msg", path: "path", value: 100)) OutputCoordinator(filePath: path).writeTheOutput([violation], reporters: [Reporter(PlainReporter())]) expect(FileManager.default.fileExists(atPath: path)).to(beFalse()) - FileManager.default.removeFileAtPath(folderPath) + + // Cleanup + FileManager.default.removeFileAtPath(filePath) } it("should write the violations in stderr") { let aComponent = TestsHelper().aComponent @@ -148,7 +128,9 @@ class OutputCoordinatorTests : QuickSpec { encoding: String.Encoding.utf16BigEndian)! let aComponent = TestsHelper().aComponent let aRule = TestsHelper().aRule - let violation = Violation(component: aComponent, rule: aRule, violationData: ViolationData(message: messageString, path: "path", value: 100)) + let violation = Violation(component: aComponent, + rule: aRule, + violationData: ViolationData(message: messageString, path: "path", value: 100)) expect(JSONCoordinator().writeViolations([violation], atPath: "")).toNot(throwError()) } } diff --git a/TaylorFrameworkTests/TemperTests/TemperTests.swift b/TaylorFrameworkTests/TemperTests/TemperTests.swift index cb07bed..607daa0 100644 --- a/TaylorFrameworkTests/TemperTests/TemperTests.swift +++ b/TaylorFrameworkTests/TemperTests/TemperTests.swift @@ -22,45 +22,46 @@ class TemperTests : QuickSpec { it("should detect the violations and create the file/files") { let aComponent = TestsHelper().aComponent let anotherComponent = TestsHelper().anotherComponent - let path = NSHomeDirectory() as NSString - let filePath = path.appendingPathComponent(JSONReporter().defaultFileName()) - let temper = Temper(outputPath: (path as String)) aComponent.components = [anotherComponent] - let content = FileContent(path: "blablabla", components: [aComponent]) - let reporter = JSONReporter() - temper.setReporters([Reporter(reporter)]) - temper.checkContent(content) + + let filePath = (NSHomeDirectory() as NSString).appendingPathComponent(JSONReporter().defaultFileName()) + let fileContent = FileContent(path: "blablabla", components: [aComponent]) + + // Tempering + let temper = Temper(outputPath: NSHomeDirectory()) + temper.setReporters([Reporter(JSONReporter())]) + temper.checkContent(fileContent) temper.finishTempering() - let jsonData = try? Data(contentsOf: URL(string: filePath)!) - guard let data = jsonData else { - return - } - var jsonResult : NSDictionary? = nil - do { - jsonResult = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary - } catch { - print("Error while creating the JSON object.") - } - guard let result = jsonResult else { - return - } - if let violations = result["violation"] as? [Dictionary] { - for violation in violations { - expect(violation["message"] as? String).toNot(beNil()) - expect(violation["rule"] as? String).toNot(beNil()) - expect(violation["path"] as? String).toNot(beNil()) - expect(violation["priority"] as? Int).toNot(beNil()) - expect(violation["externalInfoUrl"] as? String).toNot(beNil()) - expect(violation["value"] as? Int).toNot(beNil()) - expect(violation["class"] as? String).toNot(beNil()) - expect(ComponentRange.deserialize(violation)).toNot(beNil()) - } + + // Read report + guard let content = try? String(contentsOfFile: filePath) else { return fail() } + guard let data = content.data(using: .utf8) else { return fail() } + guard let jsonResult = try? JSONSerialization.jsonObject(with: data, + options: JSONSerialization.ReadingOptions.mutableContainers) + as? [String: AnyObject] else { return fail() } + guard let result = jsonResult else { return fail() } + guard let violations = result["violation"] as? [[String: AnyObject]] else { return fail() } + + // Check violations + for violation in violations { + expect(violation["message"] as? String).toNot(beNil()) + expect(violation["rule"] as? String).toNot(beNil()) + expect(violation["path"] as? String).toNot(beNil()) + expect(violation["priority"] as? Int).toNot(beNil()) + expect(violation["externalInfoUrl"] as? String).toNot(beNil()) + expect(violation["value"] as? Int).toNot(beNil()) + expect(violation["class"] as? String).toNot(beNil()) + expect(ComponentRange.deserialize(violation)).toNot(beNil()) } + + // Cleanup + FileManager.default.removeFileAtPath(filePath) } it("should set the rules limits") { let temper = Temper(outputPath: FileManager.default.currentDirectoryPath) let limits = ["ExcessiveClassLength" : 500, "ExcessiveMethodLength" : 500, "TooManyMethods" : 500, - "CyclomaticComplexity" : 500, "NestedBlockDepth" : 500, "NPathComplexity" : 500, "ExcessiveParameterList" : 500] + "CyclomaticComplexity" : 500, "NestedBlockDepth" : 500, "NPathComplexity" : 500, + "ExcessiveParameterList" : 500] temper.setLimits(limits) let rules = temper.rules for rule in rules { diff --git a/TaylorIntegrationTests/ReporterComparator.swift b/TaylorIntegrationTests/ReporterComparator.swift index 2248a87..02e9858 100644 --- a/TaylorIntegrationTests/ReporterComparator.swift +++ b/TaylorIntegrationTests/ReporterComparator.swift @@ -31,16 +31,15 @@ func !=(lhs: [String:AnyObject], rhs: [String:AnyObject]) -> Bool { return !(lhs == rhs) } -class ReporterComparator { - - func compareReporters(_ firstReporterPath: String, secondReporterPath: String) -> Bool { - var violations1 = JSONToViolationParser().parseFile(firstReporterPath) +class JSONReportComparator { + func compareReport(atPath path1: String, withReportAtPath path2: String) -> Bool { + var violations1 = JSONToViolationParser().parseFile(path1) violations1 = violations1.map { ( violation: [String:AnyObject]) -> [String:AnyObject] in var violationCopy = violation violationCopy["path"] = "" as AnyObject? return violationCopy } - var violations2 = JSONToViolationParser().parseFile(secondReporterPath) + var violations2 = JSONToViolationParser().parseFile(path2) violations2 = violations2.map { (violation: [String:AnyObject]) -> [String:AnyObject] in var violationCopy = violation violationCopy["path"] = "" as AnyObject? diff --git a/TaylorIntegrationTests/TaylorIntegrationTests.swift b/TaylorIntegrationTests/TaylorIntegrationTests.swift index 59b629e..701a33f 100644 --- a/TaylorIntegrationTests/TaylorIntegrationTests.swift +++ b/TaylorIntegrationTests/TaylorIntegrationTests.swift @@ -17,7 +17,7 @@ enum IntegrationTestsError: Error { class TaylorIntegrationTests: QuickSpec { - var runTaskPath : String { + var executableFilePath : String { let testBundle = Bundle(for: type(of: self)) let bundlePath = testBundle.bundlePath return bundlePath.stringWithoutLastComponent().stringByAppendingPathComponent("Taylor.app/Contents/MacOS/Taylor") @@ -88,6 +88,23 @@ class TaylorIntegrationTests: QuickSpec { } } + fileprivate func runWithArguments(_ arguments: String...) { + let runTask = Process() + runTask.launchPath = executableFilePath + runTask.arguments = arguments + runTask.launch() + runTask.waitUntilExit() + } + + fileprivate func removeFile(atPath path: String) { + do { + if FileManager.default.fileExists(atPath: path) { + try FileManager.default.removeItem(atPath: path) + } + } catch let error { + print(error) + } + } override func spec() { @@ -116,20 +133,27 @@ class TaylorIntegrationTests: QuickSpec { } } - it("should generate correct reports") { - let runTask = Process() - runTask.launchPath = self.runTaskPath - runTask.arguments = ["-p", self.analyzeFilesPath, "-r", "json:taylor_report.json"] - runTask.launch() - runTask.waitUntilExit() - let reporterPath = self.analyzeFilesPath.stringByAppendingPathComponent("taylor_report.json") - expect(ReporterComparator().compareReporters(self.resultFilePath, secondReporterPath: reporterPath)).to(beTrue()) - do { - if FileManager.default.fileExists(atPath: reporterPath) { - try FileManager.default.removeItem(atPath: reporterPath) - } - } catch let error { - print(error) + context("when specify report with relative path") { + it("should generate reports") { + self.runWithArguments("-p", self.analyzeFilesPath, + "-r", "json:taylor_report.json") + let reporterPath = self.analyzeFilesPath.stringByAppendingPathComponent("taylor_report.json") + let comparisonResult = JSONReportComparator().compareReport(atPath: self.resultFilePath, + withReportAtPath: reporterPath) + expect(comparisonResult).to(beTrue()) + self.removeFile(atPath: reporterPath) + } + } + + context("when specify report with absolute path") { + it("should generate reports") { + let reporterAbsolutePath = self.analyzeFilesPath.stringByAppendingPathComponent("taylor_report.json") + self.runWithArguments("-p", self.analyzeFilesPath, + "-r", "json:\(reporterAbsolutePath)") + let comparisonResult = JSONReportComparator().compareReport(atPath: self.resultFilePath, + withReportAtPath: reporterAbsolutePath) + expect(comparisonResult).to(beTrue()) + self.removeFile(atPath: reporterAbsolutePath) } }