gittest 0.1.2

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 (7) hide show
  1. data/History.txt +3 -0
  2. data/Manifest.txt +6 -0
  3. data/README.txt +65 -0
  4. data/Rakefile +12 -0
  5. data/bin/gittest +81 -0
  6. data/lib/gittest.rb +138 -0
  7. metadata +107 -0
data/History.txt ADDED
@@ -0,0 +1,3 @@
1
+ === 0.1.1 2010-12-30
2
+
3
+ * Initial release
data/Manifest.txt ADDED
@@ -0,0 +1,6 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ bin/gittest
6
+ lib/gittest.rb
data/README.txt ADDED
@@ -0,0 +1,65 @@
1
+ = Gittest
2
+
3
+ * https://github.com/thickpaddy/gittest
4
+
5
+ == Description:
6
+
7
+ Gittest uses your autotest mappings to run tests based on the files
8
+ you've created or changed, according to git diff.
9
+
10
+ == Usage:
11
+
12
+ Typically, you just execute gittest on the command line. Run it with
13
+ the help option to see what other options are available:
14
+
15
+ gittest --help
16
+
17
+ Of note is the --commit option. You can use this to customise the
18
+ commit argument to git diff, which defaults to 'HEAD', i.e. the last
19
+ commit. This is really handy when you're working on a topic branch
20
+ and want to run tests based on all the files you've changed in that
21
+ branch, not just those that have been created or modified since the
22
+ last commit. For example:
23
+
24
+ gittest --commit origin/master
25
+
26
+ You can also create a Gittest instance and both interrogate it and ask
27
+ it to run the tests (this is exactly what the executable does). Have a
28
+ look at the code, it's pretty simple.
29
+
30
+ == Install:
31
+
32
+ The latest release should be available from rubygems.org
33
+
34
+ sudo gem install gittest
35
+
36
+ To install directly from source...
37
+
38
+ git clone git://github.com/thickpaddy/gittest.git
39
+ cd gittest
40
+ rake install_gem
41
+
42
+ == License:
43
+
44
+ (The MIT License)
45
+
46
+ Copyright (c) 2010 Mark Woods
47
+
48
+ Permission is hereby granted, free of charge, to any person obtaining
49
+ a copy of this software and associated documentation files (the
50
+ 'Software'), to deal in the Software without restriction, including
51
+ without limitation the rights to use, copy, modify, merge, publish,
52
+ distribute, sublicense, and/or sell copies of the Software, and to
53
+ permit persons to whom the Software is furnished to do so, subject to
54
+ the following conditions:
55
+
56
+ The above copyright notice and this permission notice shall be
57
+ included in all copies or substantial portions of the Software.
58
+
59
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
60
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
61
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
62
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
63
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
64
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
65
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require 'rubygems'
2
+ gem 'hoe', '>= 2.1.0'
3
+ require 'hoe'
4
+ require 'fileutils'
5
+ require './lib/gittest'
6
+
7
+ Hoe.spec 'gittest' do
8
+ self.developer 'Mark Woods', 'mark dot woods at jgp, a company in the uk'
9
+ self.rubyforge_name = self.name # TODO this is default value
10
+ self.extra_deps = [['ZenTest', '>= 0']]
11
+ end
12
+
data/bin/gittest ADDED
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'optparse'
5
+ require 'gittest'
6
+
7
+ options = {:commit => 'HEAD'}
8
+ OptionParser.new do |opts|
9
+ opts.banner = "Usage: gittest [options]"
10
+ opts.on("-c MANDATORY", "--commit MANDATORY", "Commit argument for git diff command used to check for new or modified files (defaults to HEAD)") do |o|
11
+ options[:commit] = o
12
+ end
13
+ opts.on("-l", "--load", "Run pending migrations and load test database from schema before running tests (Rails only)") do |o|
14
+ options[:load] = o
15
+ end
16
+ opts.on("-p", "--prepare", "Purge test database and re-create by running all migrations before running tests (Rails only)") do |o|
17
+ options[:prepare] = o
18
+ end
19
+ opts.on("-t", "--trace", "Enable full backtrace on exception") do |o|
20
+ options[:trace] = o
21
+ end
22
+ end.parse!
23
+
24
+ # create an instance of Gittest to do the dirty work
25
+ begin
26
+ gt = Gittest.new(options[:commit])
27
+ rescue LoadError => e
28
+ puts "LoadError: #{e.message}, exiting"
29
+ if options[:trace]
30
+ puts e.backtrace
31
+ else
32
+ puts "(see full trace by running command with --trace option)"
33
+ end
34
+ exit 1
35
+ end
36
+
37
+ rake_options = options[:trace] ? '--trace' : ''
38
+ if options[:prepare]
39
+ puts "Preparing test database..."
40
+ exit $?.exitstatus unless system "rake db:test:purge #{rake_options}"
41
+ exit $?.exitstatus unless system "rake db:migrate RAILS_ENV=test #{rake_options}"
42
+ end
43
+ if options[:load]
44
+ puts "Loading test database..."
45
+ exit $?.exitstatus unless system "rake db:migrate RAILS_ENV=test #{rake_options}"
46
+ exit $?.exitstatus unless system "rake db:test:load #{rake_options}"
47
+ end
48
+
49
+ # look for modified files
50
+ if gt.new_or_modified_files.empty?
51
+ puts "No modified files, exiting"
52
+ exit
53
+ end
54
+ msg = "#{gt.new_or_modified_files.size} new or modified file"
55
+ msg << "s" unless gt.new_or_modified_files.size == 1
56
+ puts msg + ":"
57
+ gt.new_or_modified_files.each {|f| puts "\t#{f}"}
58
+
59
+ # look for files to test
60
+ if gt.files_to_test.empty?
61
+ puts "No matching files to test, exiting"
62
+ exit
63
+ end
64
+ msg = "#{gt.files_to_test.size} file"
65
+ msg << "s" unless gt.files_to_test.size == 1
66
+ msg << " to test"
67
+ puts msg + ":"
68
+ puts "\t" + gt.files_to_test.map{|k,v| k}.sort.join("\n\t")
69
+
70
+ # give user an option to quit now, before running the tests/specs
71
+ puts "Press ENTER to continue, or CTRL+C to quit"
72
+ begin
73
+ $stdin.gets # note: Kernel#gets assumes that ARGV contains a list of files from which to read next line
74
+ rescue Interrupt
75
+ exit
76
+ end
77
+
78
+ # run those tests baby
79
+ puts "Running tests and/or specs, please wait..."
80
+ gt.run_tests
81
+
data/lib/gittest.rb ADDED
@@ -0,0 +1,138 @@
1
+ require 'rubygems'
2
+ require 'autotest'
3
+ require 'rbconfig'
4
+
5
+ class Gittest
6
+
7
+ VERSION = '0.1.2'
8
+
9
+ attr_reader :commit, :test_mappings
10
+
11
+ # Create a new Gittest instance. Raises LoadError if current working directory not within a git repository. Changes current working directory to root of git repository.
12
+ def initialize(commit='HEAD')
13
+ # Force fast start option for autotest. Although not used directly here, hooks might
14
+ # do things like preparing test databases unless the fast start option is enabled.
15
+ Autotest.respond_to?(:options) ? Autotest.options[:no_full_after_start] = true : $f = true
16
+ raise LoadError, "Not in a git repository" unless silence_stream(STDERR) { system("git rev-parse") } # note: git rev-parse will exit 0 if it's in a repo
17
+ cd_to_repository_root # note: I'm assuming that the repository root is the project root, and any .autotest file will be in the project root
18
+ @at = Autotest.new
19
+ @at.hook :initialize
20
+ @at.find_files # find known files on initialisation
21
+ @test_mappings = @at.instance_eval { @test_mappings }
22
+ @commit = commit
23
+ end
24
+
25
+ # Reset the known files and both new_or_modified_files and files_to_test values
26
+ def reset
27
+ @at.find_files
28
+ @new_or_modified_files = nil
29
+ @files_to_test = nil
30
+ end
31
+
32
+ # Returns the new or modified files, initially found by calling find_new_or_modified_files
33
+ def new_or_modified_files
34
+ @new_or_modified_files ||= find_new_or_modified_files
35
+ end
36
+
37
+ # Returns the files to test, initially found by calling find_files_to_test
38
+ def files_to_test
39
+ @files_to_test ||= find_files_to_test
40
+ end
41
+
42
+ # Finds new or modified files by executing git diff and parsing output
43
+ def find_new_or_modified_files
44
+ `git diff --name-only #{@commit}`.split("\n").uniq
45
+ end
46
+
47
+ # Finds files to test by checking if the autotest test mappings match any of the new or modified files
48
+ def find_files_to_test
49
+ files_to_test = @at.new_hash_of_arrays
50
+ new_or_modified_files.each do |f|
51
+ next if f =~ @at.exceptions # skip exceptions
52
+ result = @test_mappings.find { |file_re, ignored| f =~ file_re }
53
+ unless result.nil?
54
+ [result.last.call(f, $~)].flatten.each {|match| files_to_test[match] if File.exist?(match)}
55
+ end
56
+ end
57
+ return files_to_test
58
+ end
59
+
60
+ # Runs tests and ask autotest to handle the results. Also calls autotest :run_command and :ran_command hooks appropriately.
61
+ def run_tests
62
+ @at.hook :run_command
63
+ cmd = @at.make_test_cmd(files_to_test)
64
+ # copied from Autotest#run_tests and updated to use ansi colours in TURN enabled test output and specs run with the format option set to specdoc
65
+ colors = { :red => 31, :green => 32, :yellow => 33 }
66
+ old_sync = $stdout.sync
67
+ $stdout.sync = true
68
+ results = []
69
+ line = []
70
+ begin
71
+ open("| #{cmd}", "r") do |f|
72
+ until f.eof? do
73
+ c = f.getc or break
74
+ # putc c
75
+ line << c
76
+ if c == ?\n then
77
+ str = if RUBY_VERSION >= "1.9" then
78
+ line.join
79
+ else
80
+ line.pack "c*"
81
+ end
82
+ results << str
83
+ line.clear
84
+ if str.match(/(PASS|FAIL|ERROR)$/)
85
+ # test output
86
+ case $1
87
+ when 'PASS' ; color = :green
88
+ when 'FAIL' ; color = :red
89
+ when 'ERROR' ; color = :yellow
90
+ end
91
+ print "\e[#{colors[color]}m" + str + "\e[0m"
92
+ elsif str.match(/^\- /)
93
+ # spec output
94
+ if str.match(/^\- .*(ERROR|FAILED) \- [0-9]+/)
95
+ color = $1 == 'FAILED' ? :red : :yellow
96
+ print "\e[#{colors[color]}m" + str + "\e[0m"
97
+ else
98
+ print "\e[#{colors[:green]}m" + str + "\e[0m"
99
+ end
100
+ else
101
+ print str
102
+ end
103
+ end
104
+ end
105
+ end
106
+ ensure
107
+ $stdout.sync = old_sync
108
+ end
109
+ @at.hook :ran_command
110
+ @at.handle_results(results.join)
111
+ end
112
+
113
+ private
114
+
115
+ # Changes the working directory to the root path for the repository (assumes current working directory is within a repository)
116
+ def cd_to_repository_root #:nodoc:
117
+ loop do
118
+ begin
119
+ Dir.entries('.git')
120
+ break
121
+ rescue SystemCallError
122
+ Dir.chdir('..')
123
+ next
124
+ end
125
+ end
126
+ end
127
+
128
+ # Silences a stream for the duration of the block - copied directly from Rails Kernel extensions
129
+ def silence_stream(stream) #:nodoc:
130
+ old_stream = stream.dup
131
+ stream.reopen(RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ ? 'NUL:' : '/dev/null')
132
+ stream.sync = true
133
+ yield
134
+ ensure
135
+ stream.reopen(old_stream)
136
+ end
137
+
138
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gittest
3
+ version: !ruby/object:Gem::Version
4
+ hash: 31
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 2
10
+ version: 0.1.2
11
+ platform: ruby
12
+ authors:
13
+ - Mark Woods
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-01-14 00:00:00 +00:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: ZenTest
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: hoe
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 5
44
+ segments:
45
+ - 2
46
+ - 3
47
+ - 3
48
+ version: 2.3.3
49
+ type: :development
50
+ version_requirements: *id002
51
+ description: |-
52
+ Gittest uses your autotest mappings to run tests based on the files
53
+ you've created or changed, according to git diff.
54
+ email:
55
+ - mark dot woods at jgp, a company in the uk
56
+ executables:
57
+ - gittest
58
+ extensions: []
59
+
60
+ extra_rdoc_files:
61
+ - History.txt
62
+ - Manifest.txt
63
+ - README.txt
64
+ files:
65
+ - History.txt
66
+ - Manifest.txt
67
+ - README.txt
68
+ - Rakefile
69
+ - bin/gittest
70
+ - lib/gittest.rb
71
+ has_rdoc: true
72
+ homepage: https://github.com/thickpaddy/gittest
73
+ licenses: []
74
+
75
+ post_install_message:
76
+ rdoc_options:
77
+ - --main
78
+ - README.txt
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ hash: 3
87
+ segments:
88
+ - 0
89
+ version: "0"
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ hash: 3
96
+ segments:
97
+ - 0
98
+ version: "0"
99
+ requirements: []
100
+
101
+ rubyforge_project: gittest
102
+ rubygems_version: 1.4.1
103
+ signing_key:
104
+ specification_version: 3
105
+ summary: Gittest uses your autotest mappings to run tests based on the files you've created or changed, according to git diff.
106
+ test_files: []
107
+