Skip to content

Commit

Permalink
Add tag parsing. Update readme.
Browse files Browse the repository at this point in the history
  • Loading branch information
tomleightonstars committed Apr 21, 2021
1 parent 63150ee commit 50b4d55
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 14 deletions.
7 changes: 0 additions & 7 deletions .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Feature: Feature file parsing
Given I have a working Gherkin environment
Then This test should not fail

@iOS1
@iOS1 @iOS6 @iOS7
Scenario: Nested steps
Given This step should call another step
Then This test should not fail
Expand Down
19 changes: 17 additions & 2 deletions Pod/Native/NativeFeature.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import Foundation
class NativeFeature: CustomStringConvertible {
let name: String
let featureDescription: String
let scenarios: [NativeScenario]
var scenarios: [NativeScenario]
let background: NativeBackground?

required init(name: String, description: String, scenarios: [NativeScenario], background: NativeBackground?) {
Expand Down Expand Up @@ -62,6 +62,7 @@ extension NativeFeature {
var background: NativeBackground?
var featureDescription: [String]?
var scenarioTags: [String] = []
var featureTags: [String] = []

func saveBackgroundOrScenarioAndUpdateParseState(_ lineSuffix: String){
let description = state.description.joined(separator: "\n")
Expand All @@ -83,10 +84,20 @@ extension NativeFeature {

// Filter comments (#) and tags (@), also filter white lines
guard line.first != "#" && !line.isEmpty else { continue }

// Adds Feature tags to each Scenario within the Feature
if !featureTags.isEmpty && !scenarioTags.contains(where: featureTags.contains) {
scenarioTags.append(contentsOf: featureTags)
}

if line.first == "@" {
scenarioTags.append(String(line.dropFirst()))
let tags = String(line).replacingOccurrences(of: "@", with: "")
.components(separatedBy: " ")
.filter{ !$0.isEmpty }
scenarioTags.append(contentsOf: tags)
continue
}

if let (linePrefix, lineSuffix) = line.lineComponents() {
switch linePrefix {
case Language.current.keywords.Background:
Expand All @@ -107,6 +118,10 @@ extension NativeFeature {
case Language.current.keywords.ExampleLine:
state.exampleLines.append((lineIndex+1, lineSuffix))
case Language.current.keywords.Feature:
// Gets all Feature tags
if !scenarioTags.isEmpty {
featureTags = scenarioTags
}
scenarioTags = []
default:
break
Expand Down
20 changes: 17 additions & 3 deletions Pod/Native/NativeFeatureParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,30 @@ struct NativeFeatureParser {
values.isDirectory == false else {
return nil
}
return self.parseFeatureFile(entry as! URL)

return self.parseFeatureFile(entry as! URL)!
}
}

private func parseFeatureFile(_ file: URL) -> NativeFeature? {
if file.pathExtension != "feature" { return nil }
guard let feature = NativeFeature(contentsOfURL: file) else {
guard var feature = NativeFeature(contentsOfURL: file) else {
assertionFailure("Could not parse feature at URL \(file.description)")
return nil
}

if let userTagsArgumentIndex = CommandLine.arguments.firstIndex(where: { $0.hasPrefix("Tags=") }) {
let userTags = CommandLine.arguments[userTagsArgumentIndex].replacingOccurrences(of: "Tags=", with: "")
.replacingOccurrences(of: "@", with: "")
.components(separatedBy: ",")
.filter{ !$0.isEmpty }
if userTags.count == 0 { return feature }
for index in (0...feature.scenarios.count-1).reversed() {
if !feature.scenarios[index].tags.contains(where: userTags.contains) {
feature.scenarios.remove(at: index)
}
}
}

return feature
}
}
6 changes: 5 additions & 1 deletion Pod/Native/NativeScenario.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class NativeScenario: CustomStringConvertible {
`selectorName` would be `test003TestFunnyThingsAreFunny`
*/
var selectorString: String {
get { return "test\(self.name.camelCaseify)" }
get { return "test\(self.leftPad(index))\(self.name.camelCaseify)" }
}

var selectorCString: UnsafeMutablePointer<Int8> {
Expand All @@ -44,6 +44,10 @@ class NativeScenario: CustomStringConvertible {
var description: String {
return "<\(type(of: self)) \(self.selectorString) \(self.stepDescriptions.count) steps>"
}

private func leftPad(_ index: Int) -> NSString {
return NSString(format: "%03i", index)
}
}

class NativeScenarioOutline: NativeScenario {
Expand Down
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,25 @@ There is an example of this in the Example/ project as part of this pod. Look at

The advantages of this are obvious; you get to quickly run your existing feature files and can get up and running quickly. The disadvanages are beacuse the tests are generated at runtime they can't be run individually from inside Xcode so debugging is tricker. I would use this to start testing inside Xcode but if it gets hairy, convert that feature file into a native Swift test and debug from there.

### Running using tags

You can use tags to run a subsection of your tests. These can be at Feature level, or on individual Scenarios. Tags must start with "@" and must not contain any spaces.

For Feature level tags, ensure these are before your Feature name declaration in your feature file.
For Scenario level tags, ensure these are before your Scenario name declaration in your feature file.
There can be multiple on a single line, or individual tags on individual lines.

To run using the tags:
#### CLI:
Append `-Tags=@tagName1,@tagName2` to your CLI command, swapping out @tagName1/2 for your tag names.

#### Test Plan:
Within Xcode
1. Go to edit your test plan
1. Select the 'Configurations' tab
1. Open the 'Arguments' section
1. For the 'Arguments Passed On Launch' field, enter the value 'Tags=@tagName1,@tagName2', replacing '@tagName1,@tagName2' with your tag names
1. Now run your tests in the UI using your Test Plan

### Localisation of feature files

Expand Down

0 comments on commit 50b4d55

Please sign in to comment.