infinity_test 0.1.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 (83) hide show
  1. data/.gitignore +10 -0
  2. data/.infinity_test +8 -0
  3. data/.rspec +1 -0
  4. data/.rvmrc +1 -0
  5. data/Gemfile +11 -0
  6. data/Rakefile +49 -0
  7. data/Readme.markdown +92 -0
  8. data/Tasks +5 -0
  9. data/VERSION.yml +5 -0
  10. data/bin/infinity_test +7 -0
  11. data/buzz_images/buzz_lightyear.jpg +0 -0
  12. data/buzz_images/buzz_lightyear_continencia.gif +0 -0
  13. data/buzz_images/to_infinity_and_beyond.png +0 -0
  14. data/features/infinity_test.feature +36 -0
  15. data/features/support/env.rb +1 -0
  16. data/images/faces/failure.png +0 -0
  17. data/images/faces/pending.png +0 -0
  18. data/images/faces/sucess.png +0 -0
  19. data/images/hands/failure.png +0 -0
  20. data/images/hands/pending.png +0 -0
  21. data/images/hands/sucess.png +0 -0
  22. data/images/mario_bros/failure.jpg +0 -0
  23. data/images/mario_bros/pending.jpg +0 -0
  24. data/images/mario_bros/sucess.jpg +0 -0
  25. data/images/rails/failure.png +0 -0
  26. data/images/rails/pending.png +0 -0
  27. data/images/rails/sucess.png +0 -0
  28. data/images/rubies/failure.png +0 -0
  29. data/images/rubies/pending.png +0 -0
  30. data/images/rubies/sucess.png +0 -0
  31. data/images/simpson/failure.gif +0 -0
  32. data/images/simpson/pending.jpg +0 -0
  33. data/images/simpson/sucess.jpg +0 -0
  34. data/images/street_fighter/failure.gif +0 -0
  35. data/images/street_fighter/pending.gif +0 -0
  36. data/images/street_fighter/sucess.jpg +0 -0
  37. data/images/toy_story/failure.gif +0 -0
  38. data/images/toy_story/pending.png +0 -0
  39. data/images/toy_story/sucess.png +0 -0
  40. data/infinity_test.gemspec +168 -0
  41. data/lib/infinity_test.rb +31 -0
  42. data/lib/infinity_test/application.rb +168 -0
  43. data/lib/infinity_test/binary_path.rb +21 -0
  44. data/lib/infinity_test/command.rb +57 -0
  45. data/lib/infinity_test/configuration.rb +157 -0
  46. data/lib/infinity_test/continuous_testing.rb +62 -0
  47. data/lib/infinity_test/dependencies.rb +45 -0
  48. data/lib/infinity_test/notifications/growl.rb +15 -0
  49. data/lib/infinity_test/notifications/lib_notify.rb +11 -0
  50. data/lib/infinity_test/options.rb +52 -0
  51. data/lib/infinity_test/rspec.rb +87 -0
  52. data/lib/infinity_test/runner.rb +30 -0
  53. data/lib/infinity_test/test_unit.rb +74 -0
  54. data/lib/infinity_test/test_unit_loader.rb +5 -0
  55. data/spec/factories/buzz/lib/buzz.rb +0 -0
  56. data/spec/factories/buzz/spec/buzz_spec.rb +0 -0
  57. data/spec/factories/company/lib/company.rb +0 -0
  58. data/spec/factories/company/test/company_test.rb +0 -0
  59. data/spec/factories/images/failure.png +0 -0
  60. data/spec/factories/images/pending.png +0 -0
  61. data/spec/factories/images/sucess.png +0 -0
  62. data/spec/factories/infinity_test +5 -0
  63. data/spec/factories/infinity_test_example +7 -0
  64. data/spec/factories/slinky/spec/slinky/slinky_spec.rb +0 -0
  65. data/spec/factories/travel/lib/travel.rb +0 -0
  66. data/spec/factories/travel/test/partner_test.rb +0 -0
  67. data/spec/factories/travel/test/travel_test.rb +0 -0
  68. data/spec/factories/wood/lib/wood.rb +0 -0
  69. data/spec/factories/wood/spec/wood_spec.rb +0 -0
  70. data/spec/infinity_test/application_spec.rb +149 -0
  71. data/spec/infinity_test/command_spec.rb +47 -0
  72. data/spec/infinity_test/configuration_spec.rb +196 -0
  73. data/spec/infinity_test/continuous_testing_spec.rb +7 -0
  74. data/spec/infinity_test/notifications/growl_spec.rb +9 -0
  75. data/spec/infinity_test/notifications/lib_notify_spec.rb +9 -0
  76. data/spec/infinity_test/options_spec.rb +69 -0
  77. data/spec/infinity_test/rspec_spec.rb +189 -0
  78. data/spec/infinity_test/runner_spec.rb +34 -0
  79. data/spec/infinity_test/test_unit_spec.rb +182 -0
  80. data/spec/infinity_test_spec.rb +29 -0
  81. data/spec/spec.opts +1 -0
  82. data/spec/spec_helper.rb +67 -0
  83. metadata +226 -0
@@ -0,0 +1,31 @@
1
+ require 'infinity_test/dependencies'
2
+
3
+ module InfinityTest
4
+ autoload :Application, 'infinity_test/application'
5
+ autoload :BinaryPath, 'infinity_test/binary_path'
6
+ autoload :Command, 'infinity_test/command'
7
+ autoload :Configuration, 'infinity_test/configuration'
8
+ autoload :ContinuousTesting, 'infinity_test/continuous_testing'
9
+ autoload :Options, 'infinity_test/options'
10
+ autoload :Rspec, 'infinity_test/rspec'
11
+ autoload :Runner, 'infinity_test/runner'
12
+ autoload :TestUnit, 'infinity_test/test_unit'
13
+
14
+ def self.application
15
+ @application ||= Application.new
16
+ end
17
+
18
+ def self.configuration
19
+ @configuration ||= Configuration.new
20
+ end
21
+
22
+ def self.start!
23
+ Runner.new(Options.new(ARGV)).run!
24
+ end
25
+
26
+ module Notifications
27
+ autoload :Growl, 'infinity_test/notifications/growl'
28
+ autoload :LibNotify, 'infinity_test/notifications/lib_notify'
29
+ end
30
+
31
+ end
@@ -0,0 +1,168 @@
1
+ module InfinityTest
2
+ class Application
3
+ include Notifications
4
+
5
+ attr_accessor :config, :library_directory_pattern
6
+
7
+ # Initialize the Application object with the configuration instance to
8
+ # load configuration and set properly
9
+ #
10
+ def initialize
11
+ @config = InfinityTest.configuration
12
+ @library_directory_pattern = "^lib/*/(.*)\.rb"
13
+ end
14
+
15
+ # Load the Configuration file
16
+ #
17
+ # Load first global file in => ~/.infinity_test
18
+ # After load the project file => ./.infinity_test
19
+ #
20
+ # If the Project file has the same methods in the global, will override the configurations
21
+ #
22
+ # Example:
23
+ #
24
+ # ~/.infinity_test -> infinity_test { notifications :growl }
25
+ #
26
+ # ./.infinity_test -> infinity_test { notifications :lib_notify } # High Priority
27
+ #
28
+ # After the load the Notifications Framework will be Lib Notify
29
+ #
30
+ def load_configuration_file
31
+ load_global_configuration # Separate global and local configuration
32
+ load_project_configuration # because it's more easy to test
33
+ end
34
+
35
+ def sucess_image
36
+ config.sucess_image
37
+ end
38
+
39
+ def failure_image
40
+ config.failure_image
41
+ end
42
+
43
+ def pending_image
44
+ config.pending_image
45
+ end
46
+
47
+ # Return the block object setting in the config file
48
+ #
49
+ def before_callback
50
+ config.before_callback
51
+ end
52
+
53
+ # Return the block object setting in the config file
54
+ #
55
+ def after_callback
56
+ config.after_callback
57
+ end
58
+
59
+ # Return the rubies setting in the config file or the command line
60
+ #
61
+ def rubies
62
+ config.rubies
63
+ end
64
+
65
+ def construct_commands
66
+ test_framework.construct_commands
67
+ end
68
+
69
+ def test_directory_pattern
70
+ test_framework.test_directory_pattern
71
+ end
72
+
73
+ # Return a instance of the test framework class
74
+ #
75
+ def test_framework
76
+ @test_framework ||= setting_test_framework
77
+ end
78
+
79
+ # Return a instance of the Notification Framework class
80
+ #
81
+ def notification_framework
82
+ @notification_framework ||= setting_notification
83
+ end
84
+
85
+ def run!(commands)
86
+ before_callback.call if before_callback
87
+ commands.each do |ruby_version, command|
88
+ puts; puts "* { :ruby => #{ruby_version} }"
89
+ puts command if verbose?
90
+ command = Command.new(:ruby_version => ruby_version, :command => command).run!
91
+ notify!(:results => command.results, :ruby_version => ruby_version)
92
+ end
93
+ after_callback.call if after_callback
94
+ end
95
+
96
+ def notify!(options)
97
+ message = parse_results(options[:results])
98
+ notification_framework.notify(:title => options[:ruby_version], :message => message, :image => image_to_show)
99
+ end
100
+
101
+ def parse_results(results)
102
+ test_framework.parse_results(results)
103
+ end
104
+
105
+ def image_to_show
106
+ if test_framework.failure?
107
+ failure_image
108
+ elsif test_framework.pending?
109
+ pending_image
110
+ else
111
+ sucess_image
112
+ end
113
+ end
114
+
115
+ def run_changed_lib_file(file)
116
+ file = File.basename(file[1])
117
+ files = test_framework.all_files.grep(/#{file}/i)
118
+ run_commands_for_file(files.join(' ')) unless files.empty?
119
+ end
120
+
121
+ def run_changed_test_file(file)
122
+ run_commands_for_file(file)
123
+ end
124
+
125
+ def run_commands_for_file(file)
126
+ commands = test_framework.construct_commands(file)
127
+ run!(commands)
128
+ end
129
+
130
+ def verbose?
131
+ config.verbose
132
+ end
133
+
134
+ private
135
+
136
+ def setting_test_framework
137
+ case config.test_framework
138
+ when :rspec
139
+ Rspec.new :rubies => rubies
140
+ when :test_unit
141
+ TestUnit.new :rubies => rubies
142
+ end
143
+ end
144
+
145
+ def setting_notification
146
+ case config.notification_framework
147
+ when :growl
148
+ Growl.new
149
+ when :lib_notify
150
+ LibNotify.new
151
+ end
152
+ end
153
+
154
+ def load_global_configuration
155
+ load_file :file => File.expand_path('~/.infinity_test')
156
+ end
157
+
158
+ def load_project_configuration
159
+ load_file :file => './.infinity_test'
160
+ end
161
+
162
+ def load_file(options)
163
+ file = options[:file]
164
+ load(file) if File.exist?(file)
165
+ end
166
+
167
+ end
168
+ end
@@ -0,0 +1,21 @@
1
+ module InfinityTest
2
+ module BinaryPath
3
+
4
+ def rvm_bin_path(environment, binary)
5
+ "~/.rvm/gems/#{environment.expanded_name}/bin/#{binary}"
6
+ end
7
+
8
+ def print_message(gem_name, ruby_version)
9
+ puts "\n Ruby => #{ruby_version}: I searched the #{gem_name} binary path and I don't find nothing. You have the #{gem_name} installed in this version?"
10
+ end
11
+
12
+ def search_binary(binary_name, options)
13
+ File.expand_path(rvm_bin_path(options[:environment], binary_name))
14
+ end
15
+
16
+ def have_binary?(binary)
17
+ File.exist?(binary)
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,57 @@
1
+ module InfinityTest
2
+ class Command
3
+ attr_accessor :command, :results, :line, :ruby_version
4
+
5
+ # Create new Command object that receive the ruby_version and the command string
6
+ #
7
+ def initialize(options={})
8
+ @command = options[:command]
9
+ @ruby_version = options[:ruby_version]
10
+ @results = []
11
+ @line = []
12
+ end
13
+
14
+ # Code taken in Autotest gem and change a little
15
+ #
16
+ def run!
17
+ old_sync = $stdout.sync
18
+ $stdout.sync = true
19
+ begin
20
+ open("| #{@command}", "r") do |file|
21
+ until file.eof? do
22
+ test_line = file.getc
23
+ break unless test_line
24
+ putc(test_line)
25
+ @line.push(test_line)
26
+ push_in_the_results(test_line)
27
+ end
28
+ end
29
+ ensure
30
+ $stdout.sync = old_sync
31
+ end
32
+ @results = @results.join
33
+ self
34
+ end
35
+
36
+ # Push in the results the test line
37
+ # If have in the Ruby Enterpise Edition pack the numbers return. Join otherwise.
38
+ #
39
+ def push_in_the_results(test_line)
40
+ if end_of_line?(test_line)
41
+ @results.push(ree? ? @line.pack('c*') : @line.join)
42
+ @line.clear
43
+ end
44
+ end
45
+
46
+ # Using Ruby Enterprise Edition?
47
+ #
48
+ def ree?
49
+ RVM::Environment.current_ruby_string =~ /ree/
50
+ end
51
+
52
+ def end_of_line?(test_line)
53
+ test_line == ?\n
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,157 @@
1
+ module InfinityTest
2
+ class Configuration
3
+
4
+ SUPPORTED_FRAMEWORKS = [:growl, :lib_notify] # :snarl, :lib_notify
5
+
6
+ attr_accessor :notification_framework, :sucess_image, :failure_image, :pending_image, :rubies, :test_framework,
7
+ :exceptions_to_ignore, :before_callback, :after_callback, :verbose
8
+
9
+ IMAGES_DIR = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'images'))
10
+
11
+ # Initialize the Configuration object that keeps the images, callbacks, rubies
12
+ # and the test framework
13
+ #
14
+ def initialize
15
+ @default_dir_image = File.join(IMAGES_DIR, 'simpson')
16
+ @sucess_image = 'sucess'
17
+ @failure_image = 'failure'
18
+ @pending_image = 'pending'
19
+ @test_framework = :test_unit
20
+ @verbose = false
21
+ end
22
+
23
+ # Set the notification framework to use with Infinity Test.
24
+ # The supported Notification Frameworks are:
25
+ #
26
+ # * Growl
27
+ # * Lib-Notify
28
+ #
29
+ # Here is the example of little Domain Specific Language to use:
30
+ #
31
+ # notifications :growl do
32
+ # # block
33
+ # end
34
+ #
35
+ def notifications(framework, &block)
36
+ raise NotificationFrameworkDontSupported, "Notification :#{framework} don't supported. The Frameworks supported are: #{SUPPORTED_FRAMEWORKS.join(',')}" unless SUPPORTED_FRAMEWORKS.include?(framework)
37
+ @notification_framework = framework
38
+ yield self if block_given?
39
+ self
40
+ end
41
+
42
+ # Set the Success and Failure image to show in the notification framework
43
+ #
44
+ # show_images :failure => 'Users/tomas/images/my_custom_image.png', :sucess => 'custom_image.jpg'
45
+ #
46
+ # Or you cant set modes(directory) for show images (please see the images folder in => http://github.com/tomas-stefano/infinity_test/tree/master/images/ )
47
+ #
48
+ # show_images :mode => :simpson # => This will show images in the folder http://github.com/tomas-stefano/infinity_test/tree/master/images/simpson
49
+ # show_images :mode => :street_fighter # => This will show images in folder http://github.com/tomas-stefano/infinity_test/tree/master/images/street_fighter
50
+ # show_images :mode => '~/My/Mode' # => This will show images in the '~/My/Mode' directory
51
+ #
52
+ # The Convention in images folder is to set sucess, failure and pending images, and
53
+ # Infinity test will work on these names in the notification framework
54
+ #
55
+ def show_images(options={})
56
+ switch_mode!(options[:mode]) if options[:mode]
57
+ @sucess_image = setting_image(options[:sucess]) || search_image(@sucess_image)
58
+ @failure_image = setting_image(options[:failure]) || search_image(@failure_image)
59
+ @pending_image = setting_image(options[:pending]) || search_image(@pending_image)
60
+ end
61
+
62
+ # Switch the image directory to show
63
+ #
64
+ def switch_mode!(mode)
65
+ case mode
66
+ when Symbol
67
+ @default_dir_image = File.join(IMAGES_DIR, mode.to_s)
68
+ when String
69
+ @default_dir_image = File.expand_path(File.join(mode))
70
+ end
71
+ end
72
+
73
+ def setting_image(image)
74
+ image unless image.equal?(:default)
75
+ end
76
+
77
+ # Search the sucess, failure or pending images and return the first in the pattern
78
+ #
79
+ def search_image(file)
80
+ Dir.glob(File.join(@default_dir_image, file) + '*').first
81
+ end
82
+
83
+ # The options method to set:
84
+ #
85
+ # * test framework
86
+ # * ruby versions
87
+ #
88
+ # Here is the example of Little Domain Language:
89
+ #
90
+ # use :rubies => ['1.9.1', '1.9.2'], :test_framework => :rspec
91
+ #
92
+ # use :rubies => [ '1.8.7-p249', '1.9.2@rails3'], :test_framework => :test_unit
93
+ #
94
+ def use(options={})
95
+ rubies = options[:rubies]
96
+ @rubies = (rubies.is_a?(Array) ? rubies.join(',') : rubies) || []
97
+ @test_framework = options[:test_framework] || @test_framework
98
+ @verbose = options[:verbose] || @verbose
99
+ if options[:gemset]
100
+ @rubies = @rubies.split(',').collect { |ruby| ruby << "@#{options[:gemset]}" }.join(',')
101
+ end
102
+ end
103
+
104
+ # Method to use to ignore some dir/files changes
105
+ #
106
+ # Example:
107
+ #
108
+ # ignore :exceptions => %w(.svn .hg .git vendor tmp config rerun.txt)
109
+ #
110
+ # This is useless right now in the Infinity Test because the library
111
+ # only monitoring lib and test/spec/feature folder.
112
+ #
113
+ def ignore(options={})
114
+ @exceptions_to_ignore = options[:exceptions] || []
115
+ end
116
+
117
+ # Callback method to run anything you want, before the run the test suite command
118
+ #
119
+ # Example:
120
+ #
121
+ # before_run do
122
+ # clear :terminal
123
+ # end
124
+ #
125
+ def before_run(&block)
126
+ @before_callback = block
127
+ end
128
+
129
+ # Callback method to run anything you want, after the run the test suite command
130
+ #
131
+ # Example:
132
+ #
133
+ # after_run do
134
+ # # some code that I want to run after all the rubies run
135
+ # end
136
+ #
137
+ def after_run(&block)
138
+ @after_callback = block
139
+ end
140
+
141
+ # Clear the terminal (Useful in the before callback)
142
+ #
143
+ def clear(option)
144
+ system('clear') if option == :terminal
145
+ end
146
+
147
+ end
148
+ end
149
+
150
+ class NotificationFrameworkDontSupported < StandardError
151
+ end
152
+
153
+ def infinity_test(&block)
154
+ configuration = InfinityTest.configuration
155
+ configuration.instance_eval(&block)
156
+ configuration
157
+ end
@@ -0,0 +1,62 @@
1
+ module InfinityTest
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
16
+
17
+ def run!(commands)
18
+ @application.run!(commands) unless commands.empty?
19
+ end
20
+
21
+ ##################
22
+ # Watchr Methods #
23
+ #################
24
+
25
+ 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
+ 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
38
+ end
39
+
40
+ def add_rule(script, options={})
41
+ script.watch(options[:rule]) do |file|
42
+ @application.run_changed_test_file(file)
43
+ end
44
+ end
45
+
46
+ def add_signal
47
+ Signal.trap 'INT' do
48
+ if @sent_an_int then
49
+ puts " Shutting down now"
50
+ exit
51
+ else
52
+ puts " Interrupt a second time to quit"
53
+ @sent_an_int = true
54
+ Kernel.sleep 1.1
55
+ run! @global_commands
56
+ @sent_an_int = false
57
+ end
58
+ end
59
+ end
60
+
61
+ end
62
+ end