infinity_test 0.2.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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