From 937a0164b119486b4888057f7d6ef3864605d8ea Mon Sep 17 00:00:00 2001 From: Ary Borenszweig <aborenszweig@manas.com.ar> Date: Wed, 5 Nov 2014 11:38:11 -0300 Subject: [PATCH] Spec: added `-l` switch to match against a line. Compiler: can run `crystal spec file:line` --- src/compiler/crystal/command.cr | 18 +++++++++++++++++- src/spec/context.cr | 10 +++++----- src/spec/source.cr | 20 ++++++++++++++++++++ src/spec/spec.cr | 24 ++++++++++++++++++------ 4 files changed, 60 insertions(+), 12 deletions(-) create mode 100644 src/spec/source.cr diff --git a/src/compiler/crystal/command.cr b/src/compiler/crystal/command.cr index 9901361d39..1e0d7736d4 100644 --- a/src/compiler/crystal/command.cr +++ b/src/compiler/crystal/command.cr @@ -122,8 +122,24 @@ module Crystal::Command end private def self.run_specs(options) + target_filename_and_line_number = options.shift? + if target_filename_and_line_number + splitted = target_filename_and_line_number.split ':', 2 + target_filename = splitted[0] + cwd = Dir.working_directory + if target_filename.starts_with?(cwd) + target_filename = "./#{target_filename[cwd.length .. -1]}" + end + if splitted.length == 2 + target_line = splitted[1] + options << "-l" << target_line + end + else + target_filename = "spec/**" + end + compiler = Compiler.new - sources = [Compiler::Source.new("spec", %(require "spec/**"))] + sources = [Compiler::Source.new("spec", %(require "#{target_filename}"))] output_filename = tempfile "spec" diff --git a/src/spec/context.cr b/src/spec/context.cr index 970df25405..bb7f3ebdfb 100644 --- a/src/spec/context.cr +++ b/src/spec/context.cr @@ -125,11 +125,11 @@ module Spec @@contexts_stack.pop end - def self.matches?(description, pattern) - @@contexts_stack.any?(&.matches?(pattern)) || description =~ pattern + def self.matches?(description, pattern, line) + @@contexts_stack.any?(&.matches?(pattern, line)) || description =~ pattern end - def matches?(pattern) + def matches?(pattern, line) false end end @@ -147,8 +147,8 @@ module Spec @parent.report Result.new(result.kind, "#{@description} #{result.description}", result.file, result.line, result.exception) end - def matches?(pattern) - @description =~ pattern + def matches?(pattern, line) + @description =~ pattern || @line == line end end end diff --git a/src/spec/source.cr b/src/spec/source.cr new file mode 100644 index 0000000000..6a5b2c9555 --- /dev/null +++ b/src/spec/source.cr @@ -0,0 +1,20 @@ +module Spec + def self.lines_cache + @@lines_cache ||= {} of String => Array(String) + end + + def self.read_line(file, line) + return nil unless File.exists?(file) + + lines = lines_cache[file] ||= File.read_lines(file) + lines[line - 1]? + end + + def self.relative_file(file) + cwd = Dir.working_directory + if file.starts_with?(cwd) + file = ".#{file[cwd.length .. -1]}" + end + file + end +end diff --git a/src/spec/spec.cr b/src/spec/spec.cr index 641651573c..54428ec94a 100644 --- a/src/spec/spec.cr +++ b/src/spec/spec.cr @@ -48,10 +48,19 @@ module Spec @@pattern = Regex.new(Regex.escape(pattern)) end - def self.matches?(description) - pattern = @@pattern - if pattern - Spec::RootContext.matches?(description, pattern) + @@line = nil + + def self.line=(@@line) + end + + def self.matches?(description, file, line) + spec_pattern = @@pattern + spec_line = @@line + + if line == spec_line + return true + elsif spec_pattern || spec_line + Spec::RootContext.matches?(description, spec_pattern, spec_line) else true end @@ -77,7 +86,7 @@ end def it(description, file = __FILE__, line = __LINE__) return if Spec.aborted? - return unless Spec.matches?(description) + return unless Spec.matches?(description, file, line) Spec.formatter.before_example description @@ -95,7 +104,7 @@ end def pending(description, file = __FILE__, line = __LINE__, &block) return if Spec.aborted? - return unless Spec.matches?(description) + return unless Spec.matches?(description, file, line) Spec.formatter.before_example description @@ -115,6 +124,9 @@ OptionParser.parse! do |opts| opts.on("-e ", "--example STRING", "run examples whose full nested names include STRING") do |pattern| Spec.pattern = pattern end + opts.on("-l ", "--line LINE", "run examples whose line matches LINE") do |line| + Spec.line = line.to_i + end opts.on("--fail-fast", "abort the run on first failure") do Spec.fail_fast = true end -- GitLab