gittest 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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
+