infinity_test 0.2.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data/.gitignore +3 -0
  2. data/.infinity_test +30 -2
  3. data/.rspec +2 -0
  4. data/.rvmrc +1 -1
  5. data/Gemfile +10 -2
  6. data/Gemfile.lock +52 -12
  7. data/History.markdown +86 -2
  8. data/LICENSE.txt +22 -0
  9. data/Rakefile +25 -9
  10. data/Readme.markdown +47 -23
  11. data/TODO.markdown +12 -0
  12. data/Tasks +2 -3
  13. data/VERSION.yml +2 -2
  14. data/bin/infinity_test +1 -1
  15. data/features/heuristics.feature +23 -0
  16. data/features/support/env.rb +2 -0
  17. data/images/fuuu/failure.png +0 -0
  18. data/images/fuuu/pending.png +0 -0
  19. data/images/fuuu/sucess.png +0 -0
  20. data/infinity_test.gemspec +62 -29
  21. data/lib/infinity_test.rb +29 -9
  22. data/lib/infinity_test/application.rb +222 -68
  23. data/lib/infinity_test/application_library/rails.rb +94 -0
  24. data/lib/infinity_test/application_library/rubygems.rb +43 -0
  25. data/lib/infinity_test/binary_path.rb +30 -8
  26. data/lib/infinity_test/builder.rb +56 -0
  27. data/lib/infinity_test/command.rb +18 -24
  28. data/lib/infinity_test/configuration.rb +96 -44
  29. data/lib/infinity_test/continuous_testing.rb +17 -39
  30. data/lib/infinity_test/dependencies.rb +76 -41
  31. data/lib/infinity_test/environment.rb +15 -0
  32. data/lib/infinity_test/heuristics.rb +36 -0
  33. data/lib/infinity_test/heuristics_helper.rb +9 -0
  34. data/lib/infinity_test/options.rb +56 -19
  35. data/lib/infinity_test/runner.rb +25 -17
  36. data/lib/infinity_test/test_framework.rb +109 -0
  37. data/lib/infinity_test/test_library/bacon.rb +55 -0
  38. data/lib/infinity_test/test_library/cucumber.rb +22 -0
  39. data/lib/infinity_test/test_library/rspec.rb +58 -0
  40. data/lib/infinity_test/test_library/test_unit.rb +46 -0
  41. data/spec/factories/company/Gemfile +0 -0
  42. data/spec/factories/infinity_test_example +2 -2
  43. data/spec/infinity_test/application_library/rails_spec.rb +140 -0
  44. data/spec/infinity_test/application_library/rubygems_spec.rb +52 -0
  45. data/spec/infinity_test/application_spec.rb +274 -50
  46. data/spec/infinity_test/binary_path_spec.rb +72 -0
  47. data/spec/infinity_test/builder_spec.rb +7 -0
  48. data/spec/infinity_test/command_spec.rb +13 -14
  49. data/spec/infinity_test/configuration_spec.rb +183 -57
  50. data/spec/infinity_test/continuous_testing_spec.rb +19 -1
  51. data/spec/infinity_test/environment_spec.rb +23 -0
  52. data/spec/infinity_test/heuristics_helper_spec.rb +15 -0
  53. data/spec/infinity_test/heuristics_spec.rb +127 -0
  54. data/spec/infinity_test/options_spec.rb +48 -26
  55. data/spec/infinity_test/runner_spec.rb +37 -29
  56. data/spec/infinity_test/test_framework_spec.rb +127 -0
  57. data/spec/infinity_test/test_library/bacon_spec.rb +150 -0
  58. data/spec/infinity_test/test_library/cucumber_spec.rb +8 -0
  59. data/spec/infinity_test/test_library/rspec_spec.rb +185 -0
  60. data/spec/infinity_test/test_library/test_unit_spec.rb +184 -0
  61. data/spec/infinity_test_spec.rb +23 -12
  62. data/spec/spec_helper.rb +86 -30
  63. metadata +62 -32
  64. data/lib/infinity_test/notifications/growl.rb +0 -15
  65. data/lib/infinity_test/notifications/lib_notify.rb +0 -11
  66. data/lib/infinity_test/rspec.rb +0 -87
  67. data/lib/infinity_test/test_unit.rb +0 -74
  68. data/spec/infinity_test/notifications/growl_spec.rb +0 -9
  69. data/spec/infinity_test/notifications/lib_notify_spec.rb +0 -9
  70. data/spec/infinity_test/rspec_spec.rb +0 -189
  71. data/spec/infinity_test/test_unit_spec.rb +0 -182
  72. data/spec/spec.opts +0 -1
@@ -1,48 +1,26 @@
1
1
  module InfinityTest
2
2
  class ContinuousTesting
3
- attr_accessor :application, :global_commands
4
-
5
- def initialize(options)
6
- @application = options[:application]
7
- @global_commands = @application.construct_commands
8
- end
9
-
10
- # Start the Continuous Testing Server and begin to audit the files for changes
11
- #
12
- def start!
13
- run!(@global_commands)
14
- initialize_watchr!
15
- end
3
+ attr_accessor :application, :watchr, :global_commands
16
4
 
17
- def run!(commands)
18
- @application.run!(commands) unless commands.empty?
5
+ def initialize
6
+ @application = InfinityTest.application
7
+ @watchr = InfinityTest.watchr
19
8
  end
20
9
 
21
10
  ##################
22
11
  # Watchr Methods #
23
- #################
24
-
12
+ ##################
13
+
25
14
  def initialize_watchr!
26
- script = Watchr::Script.new
27
- # add_rule script, :rule => @application.library_directory_pattern
28
- watch_lib_folder(script, @application.library_directory_pattern)
29
- add_rule script, :rule => @application.test_directory_pattern
30
15
  add_signal
31
- Watchr::Controller.new(script, Watchr.handler.new).run
32
- end
33
-
34
- def watch_lib_folder(script, library_directory_pattern)
35
- script.watch(library_directory_pattern) do |file|
36
- @application.run_changed_lib_file(file)
37
- end
16
+ run_with_watchr!
38
17
  end
18
+ alias :start! :initialize_watchr!
39
19
 
40
- def add_rule(script, options={})
41
- script.watch(options[:rule]) do |file|
42
- @application.run_changed_test_file(file)
43
- end
20
+ def run_with_watchr!
21
+ Watchr::Controller.new(@watchr, Watchr.handler.new).run
44
22
  end
45
-
23
+
46
24
  def add_signal
47
25
  Signal.trap 'INT' do
48
26
  if @sent_an_int then
@@ -52,11 +30,11 @@ module InfinityTest
52
30
  puts " Interrupt a second time to quit"
53
31
  @sent_an_int = true
54
32
  Kernel.sleep 1.1
55
- run! @global_commands
56
- @sent_an_int = false
57
- end
58
- end
33
+ @application.run_global_commands!
34
+ @sent_an_int = false
35
+ end
36
+ end
59
37
  end
60
-
38
+
61
39
  end
62
- end
40
+ end
@@ -1,45 +1,80 @@
1
+ module InfinityTest
2
+ class Dependencies
3
+
4
+ RVM_HOME_DIRECTORY = File.expand_path("~/.rvm/lib")
5
+
6
+ RVM_SYSTEM_WIDE_DIRECTORY = "/usr/local/rvm/lib"
7
+
8
+ RVM_LIBRARY_DIRECTORY = File.expand_path("~/.rvm/lib")
1
9
 
2
- RVM_LIBRARY_DIRECTORY = File.expand_path("~/.rvm/lib")
3
-
4
- #
5
- # Try to require the rvm in home folder
6
- # If not suceed raise a LoadError
7
- # Try to see if the user has the RVM 1.0 or higher for the RVM Ruby API
8
- # If not raise a NameError
9
- #
10
- def require_home_rvm
11
- $LOAD_PATH.unshift(RVM_LIBRARY_DIRECTORY) unless $LOAD_PATH.include?(RVM_LIBRARY_DIRECTORY)
12
- require 'rvm'
13
- RVM::Environment
14
- end
15
-
16
- # TODO: Make require with System Wide Install too
17
- #
18
- begin
19
- require_home_rvm
20
- rescue LoadError, NameError
21
- puts
22
- puts "It appears that you have not installed the RVM in #{RVM_LIBRARY_DIRECTORY} or RVM is very old.\n"
23
- puts "The RVM is installed?"
24
- puts "If not, please see http://rvm.beginrescueend.com/rvm/install/"
25
- puts "If so, try to run:"
26
- puts "\t rvm update --head"
27
- puts "If the error continues, please create an issue in http://github.com/tomas-stefano/infinity_test"
28
- puts 'Thanks :)'
29
- exit
30
- end
31
-
32
- def require_without_rubygems(options)
33
- gem_name = options[:gem]
34
- begin
35
- require gem_name
36
- rescue LoadError
37
- require 'rubygems'
38
- require gem_name
10
+
11
+ class << self
12
+
13
+ def require_rvm_ruby_api
14
+ require 'rvm'
15
+ RVM::Environment
16
+ end
17
+
18
+ #
19
+ # Try to require the rvm in home folder
20
+ # If not suceed raise a LoadError
21
+ # Try to see if the user has the RVM 1.0 or higher for the RVM Ruby API
22
+ # If not raise a NameError
23
+ #
24
+ def require_home_rvm
25
+ $LOAD_PATH.unshift(RVM_HOME_DIRECTORY) unless $LOAD_PATH.include?(RVM_HOME_DIRECTORY)
26
+ require_rvm_ruby_api
27
+ end
28
+
29
+ def require_rvm_system_wide
30
+ $LOAD_PATH.unshift(RVM_SYSTEM_WIDE_DIRECTORY) unless $LOAD_PATH.include?(RVM_SYSTEM_WIDE_DIRECTORY)
31
+ require_rvm_ruby_api
32
+ end
33
+
34
+ def try_to_require_system_wide
35
+ begin
36
+ require_rvm_system_wide
37
+ rescue LoadError, NameError
38
+ print_info_about_rvm
39
+ end
40
+ end
41
+
42
+ def require_rvm
43
+ begin
44
+ require_home_rvm
45
+ rescue LoadError, NameError
46
+ try_to_require_system_wide
47
+ end
48
+ end
49
+
50
+ def require_without_rubygems(options)
51
+ gem_name = options[:gem]
52
+ begin
53
+ require gem_name
54
+ rescue LoadError
55
+ require 'rubygems'
56
+ require gem_name
57
+ end
58
+ end
59
+
60
+ def print_info_about_rvm
61
+ puts
62
+ puts "It appears that you have not installed the RVM library in #{RVM_HOME_DIRECTORY} or in #{RVM_SYSTEM_WIDE_DIRECTORY} or RVM is very old.\n"
63
+ puts "The RVM is installed?"
64
+ puts "If not, please see http://rvm.beginrescueend.com/rvm/install/"
65
+ puts "If so, try to run:"
66
+ puts "\t rvm update --head (or if you're using the head of rvm try: rvm get head)"
67
+ puts "\nIf the error continues, please create an issue in http://github.com/tomas-stefano/infinity_test"
68
+ puts 'Thanks :)'
69
+ puts
70
+ exit
71
+ end
72
+
73
+ end
39
74
  end
40
- end
41
75
 
42
- require_without_rubygems :gem => 'watchr'
43
-
44
- require 'ostruct'
76
+ end
45
77
 
78
+ InfinityTest::Dependencies.require_rvm
79
+ InfinityTest::Dependencies.require_without_rubygems :gem => 'watchr'
80
+ InfinityTest::Dependencies.require_without_rubygems :gem => 'notifiers'
@@ -0,0 +1,15 @@
1
+ module InfinityTest
2
+ module Environment
3
+
4
+ # Run in context of each Ruby Environment, and the Ruby Version
5
+ #
6
+ def environments(&block)
7
+ raise unless block_given?
8
+ RVM.environments(rubies).each do |environment|
9
+ ruby_version = environment.environment_name
10
+ block.call(environment, ruby_version)
11
+ end
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,36 @@
1
+ module InfinityTest
2
+ class Heuristics
3
+ attr_reader :patterns, :script
4
+
5
+ def initialize
6
+ @patterns = {}
7
+ @script = InfinityTest.watchr
8
+ @application = InfinityTest.application
9
+ end
10
+
11
+ def add(pattern, &block)
12
+ @patterns[pattern] = block
13
+ @script.watch(pattern, &block) # Watchr
14
+ @patterns
15
+ end
16
+
17
+ def remove(pattern)
18
+ if pattern == :all
19
+ @patterns.clear
20
+ @script.rules.clear
21
+ else
22
+ @patterns.delete(pattern)
23
+ @script.rules.delete_if { |rule| rule.pattern == pattern }
24
+ end
25
+ end
26
+
27
+ def all
28
+ @patterns.keys
29
+ end
30
+
31
+ def run(options)
32
+ @application.run_commands_for_file(@application.files_to_run!(options))
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,9 @@
1
+ module InfinityTest
2
+ module HeuristicsHelper
3
+
4
+ def heuristics(&block)
5
+ InfinityTest.configuration.heuristics(&block)
6
+ end
7
+
8
+ end
9
+ end
@@ -2,15 +2,14 @@ require 'optparse'
2
2
 
3
3
  module InfinityTest
4
4
  class Options < Hash
5
-
5
+
6
6
  def initialize(arguments)
7
7
  super()
8
8
  @options = OptionParser.new do |options|
9
- parse_rspec(options)
10
- parse_test_unit(options)
11
- parse_rubies(options)
12
- parse_verbose(options)
13
- options.banner = [ "Usage: infinity_test [options]", "Starts a continuous test server."].join("\n")
9
+ [:test_unit, :rspec, :bacon, :rubygems, :rails, :rubies, :verbose, :patterns, :bundler, :version].each do |name|
10
+ send("parse_#{name}", options)
11
+ end
12
+ options.banner = [ "Usage: infinity_test [options]", "Starts a continuous test server."].join("\n")
14
13
  options.on_tail("--help", "You're looking at it.") do
15
14
  print options.help
16
15
  exit
@@ -18,35 +17,73 @@ module InfinityTest
18
17
  end
19
18
  @options.parse!(arguments.clone)
20
19
  end
21
-
20
+
22
21
  def parse_rspec(options)
23
- options.on('--rspec', 'Rspec Framework') do
22
+ options.on('--rspec', 'Test Framework: Rspec') do
24
23
  self[:test_framework] = :rspec
25
24
  end
26
25
  end
27
-
26
+
28
27
  def parse_test_unit(options)
29
- options.on('--test-unit', 'Test Unit') do
28
+ options.on('--test-unit', 'Test Framework: Test Unit [Default]') do
30
29
  self[:test_framework] = :test_unit
31
30
  end
32
31
  end
33
-
32
+
33
+ def parse_bacon(options)
34
+ options.on('--bacon', 'Test Framework: Bacon') do
35
+ self[:test_framework] = :bacon
36
+ end
37
+ end
38
+
34
39
  def parse_rubies(options)
35
- options.on('--rubies=rubies', 'Specify the Ruby Versions for Testing with several Rubies') do |versions|
40
+ options.on('--rubies=rubies', 'Specify the Ruby Versions for Testing with many Rubies') do |versions|
36
41
  self[:rubies] = versions
37
42
  end
38
43
  end
39
-
44
+
40
45
  def parse_verbose(options)
41
- options.on('--verbose', 'The Infinity Test dont print the commands. To print the command set this options!') do
46
+ options.on('--verbose', 'The Infinity Test dont print the commands', 'To print the commands set this option!') do
42
47
  self[:verbose] = true
43
48
  end
44
49
  end
45
-
46
- def rspec?
47
- return true if self[:test_framework].equal?(:rspec)
48
- false
50
+
51
+ def parse_rails(options)
52
+ options.on('--rails', 'Application Framework: Rails') do
53
+ self[:app_framework] = :rails
54
+ end
55
+ end
56
+
57
+ def parse_rubygems(options)
58
+ options.on('--rubygems', 'Application Framework: Rubygems (Default)') do
59
+ self[:app_framework] = :rubygems
60
+ end
61
+ end
62
+
63
+ # def parse_cucumber(options)
64
+ # options.on('--cucumber', 'Run with the Cucumber too') do
65
+ # self[:cucumber] = true
66
+ # end
67
+ # end
68
+
69
+ def parse_patterns(options)
70
+ options.on('--heuristics', 'Show all the Default Patterns and added by #heuristics method and EXIT.') do
71
+ self[:show_heuristics?] = true
72
+ end
73
+ end
74
+
75
+ def parse_bundler(options)
76
+ options.on('--skip-bundler', "InfinityTest try to use bundler if Gemfile is present. If you don't want to use this convention, set this option.") do
77
+ self[:skip_bundler?] = true
78
+ end
49
79
  end
50
80
 
81
+ def parse_version(options)
82
+ options.on("--version", "Show version and exit") do
83
+ puts InfinityTest.version
84
+ exit
85
+ end
86
+ end
87
+
51
88
  end
52
- end
89
+ end
@@ -1,30 +1,38 @@
1
1
  module InfinityTest
2
2
  class Runner
3
- attr_reader :commands, :options, :application
4
-
5
- def initialize(options)
6
- @options = options
7
- @commands = []
3
+ attr_reader :options, :application
4
+
5
+ def initialize(argv)
6
+ @options = Options.new(argv)
8
7
  @application = InfinityTest.application
9
8
  end
10
-
9
+
11
10
  def run!
12
11
  load_configuration_file_or_read_the_options!
13
- start_continuous_testing!
12
+ if @options[:show_heuristics?]
13
+ list_heuristics!
14
+ else
15
+ @application.run_global_commands!
16
+ start_continuous_testing!
17
+ end
18
+ end
19
+
20
+ def list_heuristics!
21
+ @application.heuristics.patterns.keys.each do |pattern|
22
+ puts %{- "#{pattern}"}
23
+ end
24
+ exit
14
25
  end
15
-
26
+
16
27
  def load_configuration_file_or_read_the_options!
17
- @application.load_configuration_file
18
- @application.config.use(
19
- :rubies => (options[:rubies] || @application.rubies),
20
- :test_framework => (options[:test_framework] || @application.config.test_framework),
21
- :verbose => options[:verbose] || @application.config.verbose
22
- )
28
+ @application.load_configuration_file_or_read_the_options!(@options)
23
29
  end
24
-
30
+
31
+ # Start Continuous Server using Watchr
32
+ #
25
33
  def start_continuous_testing!
26
- InfinityTest::ContinuousTesting.new(:application => @application).start!
34
+ InfinityTest::ContinuousTesting.new.start!
27
35
  end
28
36
 
29
37
  end
30
- end
38
+ end
@@ -0,0 +1,109 @@
1
+ module InfinityTest
2
+ class TestFramework
3
+ include InfinityTest::BinaryPath
4
+ include InfinityTest::Environment
5
+ include InfinityTest::Builder
6
+
7
+ binary :bundle
8
+
9
+ attr_accessor :application, :message, :rubies, :test_pattern
10
+
11
+ def initialize(options={})
12
+ @application = InfinityTest.application
13
+ @rubies = options[:rubies] || []
14
+ end
15
+
16
+ # Return all the files match by test_pattern
17
+ #
18
+ def all_files
19
+ Dir[@test_pattern].sort
20
+ end
21
+
22
+ def test_files
23
+ all_files.collect { |file| file }.join(' ')
24
+ end
25
+
26
+ def decide_files(file)
27
+ return file if file
28
+ test_files
29
+ end
30
+
31
+ # Method used in the subclasses of TestFramework
32
+ #
33
+ # Example:
34
+ #
35
+ # class Rspec < TestFramework
36
+ # parse_results :example => /(\d+) example/, :failure => /(\d+) failure/, :pending => /(\d+) pending/
37
+ # end
38
+ #
39
+ # Then will create @examples, @failure and @pending instance variables with the values in the test result
40
+ #
41
+ # Or with Test::Unit:
42
+ #
43
+ # class TestUnit < TestFramework
44
+ # parse_results :tests => /(\d+) tests/, :assertions => /(\d+) assertions/, :failures => /(\d+) failures/, :errors => /(\d+) errors/
45
+ # end
46
+ #
47
+ # Then will create @tests, @assertions, @failures and @errors instance variables with the values in the test result
48
+ #
49
+ def self.parse_results(patterns)
50
+ raise(ArgumentError, 'patterns should not be empty') if patterns.empty?
51
+ create_accessors(patterns)
52
+ define_method(:parse_results) do |results|
53
+ set_instances(:shell_result => test_message(results, patterns), :patterns => patterns)
54
+ end
55
+ end
56
+
57
+ # Create accessors for keys of the Hash passed in argument
58
+ #
59
+ # create_accessors({ :example => '...', :failure => '...'}) # => attr_accessor :example, :failure
60
+ #
61
+ def self.create_accessors(hash)
62
+ hash.keys.each do |attribute|
63
+ attr_accessor attribute
64
+ end
65
+ end
66
+
67
+ # Create the instance pass in the patterns options
68
+ #
69
+ # Useful for the parse results:
70
+ # parse_results :tests => /.../, :assertions => /.../
71
+ #
72
+ # Then will create @tests ans @assertions (the keys of the Hash)
73
+ #
74
+ def create_pattern_instance_variables(patterns, shell_result)
75
+ patterns.each do |key, pattern|
76
+ number = shell_result[pattern, 1].to_i
77
+ instance_variable_set("@#{key}", number)
78
+ end
79
+ @message = shell_result.gsub(/\e\[\d+?m/, '') # Clean ANSIColor strings
80
+ end
81
+
82
+ # Return the message of the tests
83
+ #
84
+ # test_message('0 examples, 0 failures', { :example => /(\d) example/}) # => '0 examples, 0 failures'
85
+ # test_message('....\n4 examples, 0 failures', { :examples => /(\d) examples/}) # => '4 examples, 0 failures'
86
+ #
87
+ def test_message(output, patterns)
88
+ lines = output.split("\n")
89
+ final_result = []
90
+ patterns.each do |key, pattern|
91
+ final_result << lines.select { |line| line =~ pattern }
92
+ end
93
+ final_result.flatten.last
94
+ end
95
+
96
+ private
97
+
98
+ def set_instances(options)
99
+ shell_result, patterns = options[:shell_result], options[:patterns]
100
+ if shell_result
101
+ create_pattern_instance_variables(patterns, shell_result)
102
+ else
103
+ patterns.each { |instance, pattern| instance_variable_set("@#{instance}", 1) } # set all to 1 to show that an error occurred
104
+ @message = "An exception occurred"
105
+ end
106
+ end
107
+
108
+ end
109
+ end