piggly 1.2.0 → 1.2.1

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.
data/README.markdown CHANGED
@@ -1,29 +1,54 @@
1
- # Piggly - PostgreSQL PL/pgSQL stored procedure code coverage
1
+ # Piggly - PostgreSQL PL/pgSQL stored-procedure code coverage for Ruby
2
+
3
+ ## Purpose
4
+
5
+ PL/pgSQL doesn't have much in the way of developer tools, and writing automated tests for
6
+ stored procedures can go much better when you know what you haven't tested. Code coverage
7
+ allows you to see which parts of your code haven't been executed.
2
8
 
3
9
  ## What's Piggly?
4
- Piggly is like [RCov] [1] for PostgreSQL's PL/pgSQL stored procedures. It reports on code
5
- coverage to help you identify untested parts of your code.
10
+
11
+ Piggly is a tool written in Ruby to track code coverage of PostgreSQL's PL/pgSQL stored
12
+ procedures. It reports on code coverage to help you identify untested parts of your code. You
13
+ write tests in Ruby against your stored procedures and run them with piggly.
14
+
15
+ ## How Does It Work?
16
+
17
+ Piggly tracks the execution of PostgreSQL's PL/pgSQL stored procedures by recompiling
18
+ the stored procedure with instrumentation code that uses RAISE WARNING to notify the
19
+ client of an execution event (e.g., a branch condition evaluating to true or false). It records
20
+ these events and generates prettified source code that is annotated with coverage details.
6
21
 
7
22
  ## Features
23
+
8
24
  * Branch, block, and loop coverage analysis
9
25
  * Instrumenting source-to-source compiler
10
26
  * Low test execution overhead
11
27
  * Reduced compilation times by use of disk caching
12
- * Readable and easily navigable reports (see example/piggly/reports/index.html)
13
- * Able to aggregate coverage across multiple runs
28
+ * Readable and easily-navigable reports (see example/piggly/reports/index.html)
29
+ * Possible to aggregate coverage across multiple runs
14
30
  * Test::Unit and RSpec compatible
15
31
 
16
32
  ## Limitations
33
+
17
34
  * Cannot parse aggregate definitions (but helper functions are fine)
18
35
  * Cannot parse nested dollar-quoted strings, eg $A$ ... $B$ ... $B$ ... $A$
19
36
  * Report generation is resource intensive and slow
37
+ * SQL statements are not instrumented, so their branches (COALESCE, WHERE-clauses, etc) aren't tracked
38
+ * Not all PL/pgSQL grammar is currently supported, but this is easily addressed
20
39
 
21
40
  ## Requirements
41
+
22
42
  * [Treetop] [2]
23
- * Stored procedures stored on the filesystem, defined with "CREATE OR REPLACE FUNCTION ..."
43
+ * Stored procedures stored on the filesystem, defined as `CREATE OR REPLACE FUNCTION`
24
44
  * The [ruby-pg driver] [3], and for the time being, ActiveRecord (some workaround should be possible)
25
45
 
46
+ ## How to Install
47
+
48
+ $ gem install piggly
49
+
26
50
  ## Usage
51
+
27
52
  Assume your stored procedures are in proc/, and the tests that should be exercising your
28
53
  stored procedures are in spec/.
29
54
 
@@ -57,16 +82,17 @@ stored procedures are in spec/.
57
82
  -rw-r--r-- 1 kputnam kputnam 1.3K 2010-04-19 14:25 piggly/reports/index.html
58
83
 
59
84
  Note the compilation can be slow on the first run, but on subsequent runs it shouldn't need
60
- to be compiled again. If a file is added or changed (based on mtime), it will be recompiled.
85
+ to compile everything again. If a file is added or changed (based on mtime), it will be recompiled.
61
86
 
62
87
  Piggly can also be run from Rake, with a task like:
88
+ require 'piggly/task'
63
89
 
64
90
  namespace :spec do
65
91
  Piggly::Task.new(:piggly => 'db:test:prepare') do |t|
66
92
  t.libs.push 'spec'
67
93
 
68
94
  t.test_files = FileList['spec/**/*_spec.rb']
69
- t.proc_files = FileList['procs/*.sql']
95
+ t.proc_files = FileList['proc/*.sql']
70
96
 
71
97
  # this can be used if piggly is frozen in a Rails application
72
98
  t.libs.concat Dir['vendor/gems/*/lib/'].sort.reverse
@@ -76,9 +102,15 @@ Piggly can also be run from Rake, with a task like:
76
102
 
77
103
  $ rake spec:piggly
78
104
 
105
+ ## Bugs & Issues
106
+
107
+ Please report any issues on the [github tracker] [4]
108
+
79
109
  ## Author
110
+
80
111
  * Kyle Putnam <putnam.kyle@gmail.com>
81
112
 
82
113
  [1]: http://github.com/relevance/rcov/
83
114
  [2]: http://github.com/nathansobo/treetop
84
115
  [3]: http://bitbucket.org/ged/ruby-pg/
116
+ [4]: http://github.com/kputnam/piggly/issues
data/bin/piggly CHANGED
@@ -26,6 +26,7 @@ module Piggly
26
26
  uninstall_procs(sources)
27
27
  create_index(sources)
28
28
  create_reports(sources)
29
+ exit! 0 # avoid running tests again
29
30
  end
30
31
  end
31
32
 
@@ -172,10 +173,12 @@ module Piggly
172
173
  end
173
174
 
174
175
  def execute_tests
175
- if defined? Spec::Runner
176
+ if defined? Test::Unit::AutoRunner
177
+ Test::Unit::AutoRunner.run
178
+ elsif defined? Spec::Runner
176
179
  Spec::Runner.run
177
180
  else
178
- Test::Unit::AutoRunner.run
181
+ raise "Neither RSpec nor Test::Unit were detected"
179
182
  end
180
183
  end
181
184
 
@@ -13,7 +13,7 @@ grammar Piggly
13
13
  procedureHeader
14
14
  name:tIdentifier tSpace?
15
15
  parameters:parameterList tSpace
16
- procedureReturn tSpace
16
+ procedureReturn
17
17
  return:tType tSpace kwAS tSpace
18
18
  procedureBody
19
19
  procedureFooter <Procedure>
@@ -24,7 +24,7 @@ grammar Piggly
24
24
  end
25
25
 
26
26
  rule procedureReturn
27
- 'returns' tSpace 'setof'? <TextNode>
27
+ 'returns' tSpace ( 'setof' tSpace )? <TextNode>
28
28
  end
29
29
 
30
30
  rule procedureBody
@@ -61,32 +61,28 @@ module Piggly
61
61
  elements[5]
62
62
  end
63
63
 
64
- def tSpace2
64
+ def return
65
65
  elements[6]
66
66
  end
67
67
 
68
- def return
68
+ def tSpace2
69
69
  elements[7]
70
70
  end
71
71
 
72
- def tSpace3
72
+ def kwAS
73
73
  elements[8]
74
74
  end
75
75
 
76
- def kwAS
76
+ def tSpace3
77
77
  elements[9]
78
78
  end
79
79
 
80
- def tSpace4
81
- elements[10]
82
- end
83
-
84
80
  def procedureBody
85
- elements[11]
81
+ elements[10]
86
82
  end
87
83
 
88
84
  def procedureFooter
89
- elements[12]
85
+ elements[11]
90
86
  end
91
87
  end
92
88
 
@@ -125,27 +121,23 @@ module Piggly
125
121
  r7 = _nt_procedureReturn
126
122
  s0 << r7
127
123
  if r7
128
- r8 = _nt_tSpace
124
+ r8 = _nt_tType
129
125
  s0 << r8
130
126
  if r8
131
- r9 = _nt_tType
127
+ r9 = _nt_tSpace
132
128
  s0 << r9
133
129
  if r9
134
- r10 = _nt_tSpace
130
+ r10 = _nt_kwAS
135
131
  s0 << r10
136
132
  if r10
137
- r11 = _nt_kwAS
133
+ r11 = _nt_tSpace
138
134
  s0 << r11
139
135
  if r11
140
- r12 = _nt_tSpace
136
+ r12 = _nt_procedureBody
141
137
  s0 << r12
142
138
  if r12
143
- r13 = _nt_procedureBody
139
+ r13 = _nt_procedureFooter
144
140
  s0 << r13
145
- if r13
146
- r14 = _nt_procedureFooter
147
- s0 << r14
148
- end
149
141
  end
150
142
  end
151
143
  end
@@ -280,6 +272,12 @@ module Piggly
280
272
  def tSpace
281
273
  elements[1]
282
274
  end
275
+ end
276
+
277
+ module ProcedureReturn1
278
+ def tSpace
279
+ elements[1]
280
+ end
283
281
 
284
282
  end
285
283
 
@@ -307,11 +305,24 @@ module Piggly
307
305
  r2 = _nt_tSpace
308
306
  s0 << r2
309
307
  if r2
308
+ i4, s4 = index, []
310
309
  if has_terminal?('setof', false, index)
311
- r4 = instantiate_node(SyntaxNode,input, index...(index + 5))
310
+ r5 = instantiate_node(SyntaxNode,input, index...(index + 5))
312
311
  @index += 5
313
312
  else
314
313
  terminal_parse_failure('setof')
314
+ r5 = nil
315
+ end
316
+ s4 << r5
317
+ if r5
318
+ r6 = _nt_tSpace
319
+ s4 << r6
320
+ end
321
+ if s4.last
322
+ r4 = instantiate_node(SyntaxNode,input, i4...index, s4)
323
+ r4.extend(ProcedureReturn0)
324
+ else
325
+ @index = i4
315
326
  r4 = nil
316
327
  end
317
328
  if r4
@@ -324,7 +335,7 @@ module Piggly
324
335
  end
325
336
  if s0.last
326
337
  r0 = instantiate_node(TextNode,input, i0...index, s0)
327
- r0.extend(ProcedureReturn0)
338
+ r0.extend(ProcedureReturn1)
328
339
  else
329
340
  @index = i0
330
341
  r0 = nil
data/lib/piggly/task.rb CHANGED
@@ -23,7 +23,7 @@ module Piggly
23
23
  @test_files = []
24
24
  @proc_files = []
25
25
  @ruby_opts = []
26
- @output_dir = 'piggly/output'
26
+ @report_dir = 'piggly/report'
27
27
  @cache_root = 'piggly/cache'
28
28
  @piggly_path = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'bin', 'piggly'))
29
29
  @piggly_opts = ''
@@ -47,7 +47,7 @@ module Piggly
47
47
 
48
48
  ruby opts.join(' ') + ' ' +
49
49
  @piggly_opts + ' ' +
50
- %{-o #{quote @output_dir} } +
50
+ %{-o #{quote @report_dir} } +
51
51
  %{-c #{quote @cache_root} } +
52
52
  proc_files.map{|s| %[-s "#{s}" ] }.join +
53
53
  test_files.map{|f| quote(f) }.join(' ')
@@ -2,11 +2,11 @@ module Piggly
2
2
  module VERSION
3
3
  MAJOR = 1
4
4
  MINOR = 2
5
- TINY = 0
5
+ TINY = 1
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
 
9
- RELEASE_DATE = '2010-04-19'
9
+ RELEASE_DATE = '2010-04-22'
10
10
 
11
11
  def self.to_s
12
12
  STRING
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: piggly
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kyle Putnam
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-04-19 00:00:00 +00:00
12
+ date: 2010-04-22 00:00:00 +00:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency