module CucumberAnalytics class ParsedFile attr_reader :feature attr_accessor :parent_element # Creates a new ParsedFile object and, if *file_parsed* is provided, # populates the object. def initialize(file_parsed = nil) CucumberAnalytics::Logging.logger.info('ParsedFile#initialize') parse_file(file_parsed) if file_parsed end # Returns the name of the file. def name File.basename(@file.gsub('\\', '/')) end # Returns the path of the file. def path @file end # Returns the immediate child elements of the feature file(i.e. its # feature). def contains @feature ? [@feature] : [] end # Returns the number of features contained in the file. def feature_count @feature.nil? ? 0 : 1 end private def parse_file(file_parsed) CucumberAnalytics::Logging.logger.info('ParsedFile#parse_file') CucumberAnalytics::Logging.logger.debug("Parsing file: #{file_parsed}") @file = file_parsed file_lines = [] feature_lines = [] background_lines = [] File.open(@file, 'r') { |file| file_lines = file.readlines } # collect feature tag lines until file_lines.first =~ /^\s*Feature:/ or file_lines.empty? feature_lines << file_lines.first file_lines.shift end # collect everything else until the end of the feature section until file_lines.first =~ /#{World::TEST_ELEMENT_START_PATTERN}/ or file_lines.empty? feature_lines << file_lines.first file_lines.shift end # create a new feature bases on the collected lines if feature_lines.empty? @feature = nil else found_feature = ParsedFeature.new(feature_lines) found_feature.parent_element = self @feature = found_feature end if file_lines.first =~ /^\s*Background:/ # collect the background description lines until (file_lines.first =~ /^\s*(?:(?:Given )|(?:When )|(?:Then )|(?:And )|(?:\* )|@|Scenario:|(?:Scenario Outline:))/) or file_lines.empty? background_lines << file_lines.first file_lines.shift end # collect everything else up to the first test until file_lines.first =~ /^\s*(?:@|Scenario:|(?:Scenario Outline:))/ or file_lines.empty? if file_lines.first =~ /^\s*"""/ background_lines.concat(extract_doc_string!(file_lines)) else background_lines << file_lines.first file_lines.shift end end # create a new background based on the collected lines found_background = ParsedBackground.new(background_lines) found_background.parent_element = @feature @feature.background = found_background end parse_tests(file_lines) end def parse_tests(lines) CucumberAnalytics::Logging.logger.info('ParsedFile#parse_tests') CucumberAnalytics::Logging.logger.debug('lines') lines.each do |line| CucumberAnalytics::Logging.logger.debug(line.chomp) end until lines.empty? # we'll need this in order to figure out whether we are dealing with a # scenario or an outline current_test_line = lines.index { |line| line =~ /^\s*(?:Scenario:|(?:Scenario Outline:))/ } test_lines = [] # collect the tag lines until lines.first =~ /^\s*(?:Scenario:|(?:Scenario Outline:))/ test_lines << lines.first lines.shift end test_lines << lines.first lines.shift # collect the description lines until (lines.first =~ /^\s*(?:(?:Given )|(?:When )|(?:Then )|(?:And )|(?:\* )|Scenario:|(?:Scenario Outline:))/) or lines.empty? test_lines << lines.first lines.shift end # collect everything else up to the next test until (lines.first =~ /^\s*(?:Scenario:|(?:Scenario Outline:))/) or lines.empty? if (lines.first =~ /^\s*"""/) test_lines.concat(extract_doc_string!(lines)) else test_lines << lines.first lines.shift end end # backtrack in order to not end up stealing the next test's tag lines unless lines.empty? while (test_lines.last =~ /^\s*@/) or World.ignored_line?(test_lines.last) lines = [test_lines.pop].concat(lines) end end # use the collected lines to create a scenario or an outline accordingly if test_lines[current_test_line] =~ /^\s*Scenario Outline:/ next_test = ParsedScenarioOutline.new(test_lines) else next_test = ParsedScenario.new(test_lines) end next_test.parent_element = @feature @feature.tests << next_test end end def extract_doc_string!(lines) CucumberAnalytics::Logging.logger.info('ParsedFile#extract_doc_string!') CucumberAnalytics::Logging.logger.debug('lines') lines.each do |line| CucumberAnalytics::Logging.logger.debug(line.chomp) end doc_block = [] doc_block << lines.first lines.shift until lines.first =~ /^\s*"""/ doc_block << lines.first lines.shift end doc_block << lines.first lines.shift doc_block end end end