mattwynne-cucover 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/README.markdown +31 -2
  2. data/lib/cucover.rb +57 -9
  3. metadata +3 -22
data/README.markdown CHANGED
@@ -6,14 +6,43 @@ What does it mean for Cucumber to be lazy? It will only run a feature if it need
6
6
 
7
7
  How does it decide whether it needs to run a feature? Every time you run a feature using Cucover, it watches the code in your application that is executed, and remembers. The next time you run Cucover, it skips a feature if the source files (or the feature itself) have not been changed since it was last run.
8
8
 
9
+ ## Features
10
+
11
+ * Uses RCov to map features to covered source files
12
+ * Patches Rails to also map features to covered .erb templates
13
+
9
14
  ## Installation and Usage
10
15
 
11
- There's no gem for now, so just clone the code from github.
16
+ Something like this, as I haven't figured out the dependencies yet for the gem:
17
+
18
+ sudo gem install spicycode-rcov
19
+ sudo gem install mattwynne-cucover
12
20
 
13
21
  To run your features lazily, just use the cucover binary instead of cucumber. Use the same command-line options as usual, they are all passed directly to cucumber. No magic to see here, just a little gentle duck-punching.
14
22
 
15
23
  ## Limitations
16
24
 
17
- * Cucover uses RCov to watch the code executed by each feature. RCov does not report ERB view templates so Rails views, for example, that are touched will not cause any features to be re-run.
18
25
  * Anything that runs out of process will not be covered, and therefore cannot trigger a re-run, so if you use Cucumber to drive Selenium, for example, you're out of luck.
19
26
  * This is very new and experimental. There may be bugs. Feedback is welcome via github messages.
27
+
28
+ ## Todo
29
+ * The features for cucuover itself seem to flicker (intermittently fail). This is probably due to timing issues when figuring out if a file is dirty.
30
+ * Consider making failing features run-run even when they're not dirty, just for the good old red-bar feel
31
+
32
+ ## Similar 'Selective Testing' Tools
33
+
34
+ * JTestMe
35
+ * http://xircles.codehaus.org/projects/jtestme
36
+ * [Agile2008 conference submission](http://submissions.agile2008.org/node/3435)
37
+ * Infinitest
38
+ * http://code.google.com/p/infinitest/
39
+ * Contact: [Ben Rady](http://submissions.agile2008.org/node/377)
40
+ * Google Testar
41
+ * http://code.google.com/p/google-testar/
42
+ * Contact: Misha Dmitriev
43
+ * Clover test optimization
44
+ * http://www.atlassian.com/software/clover/features/optimization.jsp
45
+ * JUnitMax
46
+ * a selective testing tool by [Kent Beck](http://www.threeriversinstitute.org/blog)
47
+ * http://junitmax.com/
48
+
data/lib/cucover.rb CHANGED
@@ -6,6 +6,15 @@ require 'rcov'
6
6
 
7
7
  module Cucover
8
8
 
9
+ class << self
10
+ def record(file)
11
+ additional_covered_files << file
12
+ end
13
+ def additional_covered_files
14
+ @additional_covered_files ||= []
15
+ end
16
+ end
17
+
9
18
  class SourceFileCache
10
19
  def initialize(feature_file)
11
20
  @feature_file = feature_file
@@ -22,10 +31,8 @@ module Cucover
22
31
  File.exist?(cache_filename)
23
32
  end
24
33
 
25
- def dirty_files
26
- source_files.select do |source_file|
27
- File.mtime(Dir.pwd + '/' + source_file.strip) > time
28
- end
34
+ def any_dirty_files?
35
+ not dirty_files.empty?
29
36
  end
30
37
 
31
38
  def time
@@ -33,6 +40,12 @@ module Cucover
33
40
  end
34
41
 
35
42
  private
43
+
44
+ def dirty_files
45
+ source_files.select do |source_file|
46
+ File.mtime(Dir.pwd + '/' + source_file.strip) >= time
47
+ end
48
+ end
36
49
 
37
50
  def source_files
38
51
  result = []
@@ -53,6 +66,7 @@ module Cucover
53
66
 
54
67
  def accept(visitor)
55
68
  return unless dirty?
69
+ Cucover.additional_covered_files.clear
56
70
  analyzer.run_hooked do
57
71
  super
58
72
  end
@@ -63,8 +77,12 @@ module Cucover
63
77
 
64
78
  def dirty?
65
79
  return true unless source_files_cache.exists?
66
- return true if File.mtime(@file) >= source_files_cache.time
67
- not source_files_cache.dirty_files.empty?
80
+ return true if changed_since_last_run?
81
+ source_files_cache.any_dirty_files?
82
+ end
83
+
84
+ def changed_since_last_run?
85
+ File.mtime(@file) >= source_files_cache.time
68
86
  end
69
87
 
70
88
  def source_files_cache
@@ -76,9 +94,11 @@ module Cucover
76
94
  end
77
95
 
78
96
  def analyzed_files
79
- normalized_files = analyzer.analyzed_files.map{ |f| File.expand_path(f).gsub(/^#{Dir.pwd}\//, '') }
80
- interesting_files = normalized_files.reject{ |f| boring?(f) }
81
- interesting_files.sort
97
+ normalized_files.reject{ |f| boring?(f) }.sort
98
+ end
99
+
100
+ def normalized_files
101
+ (analyzer.analyzed_files + Cucover.additional_covered_files.uniq).map{ |f| File.expand_path(f).gsub(/^#{Dir.pwd}\//, '') }
82
102
  end
83
103
 
84
104
  def boring?(file)
@@ -95,6 +115,30 @@ module Cucover
95
115
  super feature.extend(LazyFeature)
96
116
  end
97
117
  end
118
+
119
+ module Rails
120
+ class << self
121
+ def patch_if_necessary
122
+ return if @patched
123
+ return unless defined?(ActionView)
124
+
125
+ ActionView::Template.instance_eval do
126
+ def new(*args)
127
+ super(*args).extend(Cucover::Rails::RecordsRenders)
128
+ end
129
+ end
130
+
131
+ @patched = true
132
+ end
133
+ end
134
+
135
+ module RecordsRenders
136
+ def render
137
+ Cucover.record(@filename)
138
+ super
139
+ end
140
+ end
141
+ end
98
142
  end
99
143
 
100
144
  module Cucumber
@@ -108,3 +152,7 @@ module Cucumber
108
152
  end
109
153
  end
110
154
  end
155
+
156
+ Before do
157
+ Cucover::Rails.patch_if_necessary
158
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mattwynne-cucover
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Wynne
@@ -11,27 +11,8 @@ cert_chain: []
11
11
 
12
12
  date: 2009-03-18 00:00:00 -07:00
13
13
  default_executable:
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
16
- name: cucumber
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
20
- requirements:
21
- - - ">="
22
- - !ruby/object:Gem::Version
23
- version: "0.2"
24
- version:
25
- - !ruby/object:Gem::Dependency
26
- name: rcov
27
- type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: 0.8.1.5
34
- version:
14
+ dependencies: []
15
+
35
16
  description: Cucover is a thin wrapper for Cucumber which makes it lazy.
36
17
  email: matt@mattwynne.net
37
18
  executables: []