metric_fu 4.8.0 → 4.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.metrics +1 -66
  5. data/.travis.yml +1 -0
  6. data/CONTRIBUTORS +13 -11
  7. data/DEV.md +21 -18
  8. data/Gemfile +1 -2
  9. data/Gemfile.devtools +0 -1
  10. data/HISTORY.md +7 -1
  11. data/README.md +79 -19
  12. data/Rakefile +0 -1
  13. data/checksum/metric_fu-4.8.0.gem.sha512 +1 -0
  14. data/gem_tasks/usage_test.rake +30 -0
  15. data/lib/metric_fu/configuration.rb +6 -1
  16. data/lib/metric_fu/data_structures/line_numbers.rb +1 -1
  17. data/lib/metric_fu/environment.rb +2 -7
  18. data/lib/metric_fu/logging/mf_debugger.rb +4 -4
  19. data/lib/metric_fu/metric.rb +2 -2
  20. data/lib/metric_fu/metrics/cane/template_awesome/cane.html.erb +74 -85
  21. data/lib/metric_fu/metrics/churn/churn.rb +1 -2
  22. data/lib/metric_fu/metrics/flay/template_awesome/flay.html.erb +2 -1
  23. data/lib/metric_fu/metrics/flog/template_awesome/flog.html.erb +2 -1
  24. data/lib/metric_fu/metrics/rails_best_practices/template_awesome/rails_best_practices.html.erb +2 -1
  25. data/lib/metric_fu/metrics/rcov/external_client.rb +24 -0
  26. data/lib/metric_fu/metrics/rcov/rcov.rb +9 -100
  27. data/lib/metric_fu/metrics/rcov/rcov_format_coverage.rb +140 -0
  28. data/lib/metric_fu/metrics/rcov/simplecov_formatter.rb +64 -0
  29. data/lib/metric_fu/metrics/rcov/template_awesome/rcov.html.erb +5 -1
  30. data/lib/metric_fu/metrics/reek/reek_grapher.rb +7 -1
  31. data/lib/metric_fu/metrics/reek/template_awesome/reek.html.erb +2 -1
  32. data/lib/metric_fu/metrics/roodi/template_awesome/roodi.html.erb +2 -1
  33. data/lib/metric_fu/metrics/stats/template_awesome/stats.html.erb +2 -2
  34. data/lib/metric_fu/reporting/graphs/grapher.rb +5 -20
  35. data/lib/metric_fu/reporting/templates/awesome/awesome_template.rb +1 -1
  36. data/lib/metric_fu/reporting/templates/awesome/layout.html.erb +8 -3
  37. data/lib/metric_fu/reporting/templates/javascripts/bluff_graph.js +15 -0
  38. data/lib/metric_fu/reporting/templates/javascripts/excanvas.js +1 -1
  39. data/lib/metric_fu/reporting/templates/javascripts/highcharts.js +294 -0
  40. data/lib/metric_fu/reporting/templates/javascripts/highcharts_graph.js +38 -0
  41. data/lib/metric_fu/reporting/templates/javascripts/standalone-framework.js +17 -0
  42. data/lib/metric_fu/reporting/templates/javascripts/utils.js +9 -0
  43. data/lib/metric_fu/templates/css/bluff.css +10 -10
  44. data/lib/metric_fu/templates/css/integrity.css +3 -0
  45. data/lib/metric_fu/templates/report.html.erb +3 -4
  46. data/lib/metric_fu/version.rb +1 -1
  47. data/metric_fu.gemspec +1 -0
  48. data/spec/fixtures/coverage.rb +13 -0
  49. data/spec/fixtures/exit0.sh +3 -0
  50. data/spec/fixtures/exit1.sh +3 -0
  51. data/spec/metric_fu/formatter/html_spec.rb +2 -2
  52. data/spec/metric_fu/metrics/rcov/simplecov_formatter_spec.rb +41 -0
  53. data/spec/spec_helper.rb +7 -8
  54. data/spec/support/usage_test.rb +134 -0
  55. data/spec/usage_test_spec.rb +69 -0
  56. metadata +39 -3
  57. metadata.gz.sig +0 -0
@@ -0,0 +1,38 @@
1
+ createGraphElement("div");
2
+
3
+ if(document.getElementById('graph')) {
4
+ var chart = new Highcharts.Chart({
5
+ chart: {
6
+ animation: false,
7
+ renderTo: 'graph'
8
+ },
9
+ legend: {
10
+ align: 'center',
11
+ verticalAlign: 'top',
12
+ y: 25
13
+ },
14
+ plotOptions: {
15
+ line: {
16
+ animation: false,
17
+ lineWidth: 3,
18
+ marker: {
19
+ radius: 6
20
+ },
21
+ pointPlacement: 'on'
22
+ }
23
+ },
24
+ title: {
25
+ text: graph_title
26
+ },
27
+ xAxis: {
28
+ categories: graph_labels,
29
+ tickmarkPlacement: 'on'
30
+ },
31
+ yAxis: {
32
+ maxPadding: 0,
33
+ min: 0,
34
+ minPadding: 0
35
+ },
36
+ series: graph_series
37
+ });
38
+ }
@@ -0,0 +1,17 @@
1
+ /*
2
+ Highcharts JS v3.0.9 (2014-01-15)
3
+
4
+ Standalone Highcharts Framework
5
+
6
+ License: MIT License
7
+ */
8
+ var HighchartsAdapter=function(){function o(c){function b(b,a,d){b.removeEventListener(a,d,!1)}function d(b,a,d){d=b.HCProxiedMethods[d.toString()];b.detachEvent("on"+a,d)}function a(a,c){var f=a.HCEvents,i,g,k,j;if(a.removeEventListener)i=b;else if(a.attachEvent)i=d;else return;c?(g={},g[c]=!0):g=f;for(j in g)if(f[j])for(k=f[j].length;k--;)i(a,j,f[j][k])}c.HCExtended||Highcharts.extend(c,{HCExtended:!0,HCEvents:{},bind:function(a,b){var d=this,c=this.HCEvents,g;if(d.addEventListener)d.addEventListener(a,
9
+ b,!1);else if(d.attachEvent){g=function(a){b.call(d,a)};if(!d.HCProxiedMethods)d.HCProxiedMethods={};d.HCProxiedMethods[b.toString()]=g;d.attachEvent("on"+a,g)}c[a]===r&&(c[a]=[]);c[a].push(b)},unbind:function(c,h){var f,i;c?(f=this.HCEvents[c]||[],h?(i=HighchartsAdapter.inArray(h,f),i>-1&&(f.splice(i,1),this.HCEvents[c]=f),this.removeEventListener?b(this,c,h):this.attachEvent&&d(this,c,h)):(a(this,c),this.HCEvents[c]=[])):(a(this),this.HCEvents={})},trigger:function(a,b){var d=this.HCEvents[a]||
10
+ [],c=d.length,g,k,j;k=function(){b.defaultPrevented=!0};for(g=0;g<c;g++){j=d[g];if(b.stopped)break;b.preventDefault=k;b.target=this;if(!b.type)b.type=a;j.call(this,b)===!1&&b.preventDefault()}}});return c}var r,l=document,p=[],m=[],q,n;Math.easeInOutSine=function(c,b,d,a){return-d/2*(Math.cos(Math.PI*c/a)-1)+b};return{init:function(c){if(!l.defaultView)this._getStyle=function(b,d){var a;return b.style[d]?b.style[d]:(d==="opacity"&&(d="filter"),a=b.currentStyle[d.replace(/\-(\w)/g,function(b,a){return a.toUpperCase()})],
11
+ d==="filter"&&(a=a.replace(/alpha\(opacity=([0-9]+)\)/,function(b,a){return a/100})),a===""?1:a)},this.adapterRun=function(b,d){var a={width:"clientWidth",height:"clientHeight"}[d];if(a)return b.style.zoom=1,b[a]-2*parseInt(HighchartsAdapter._getStyle(b,"padding"),10)};if(!Array.prototype.forEach)this.each=function(b,d){for(var a=0,c=b.length;a<c;a++)if(d.call(b[a],b[a],a,b)===!1)return a};if(!Array.prototype.indexOf)this.inArray=function(b,d){var a,c=0;if(d)for(a=d.length;c<a;c++)if(d[c]===b)return c;
12
+ return-1};if(!Array.prototype.filter)this.grep=function(b,d){for(var a=[],c=0,h=b.length;c<h;c++)d(b[c],c)&&a.push(b[c]);return a};n=function(b,c,a){this.options=c;this.elem=b;this.prop=a};n.prototype={update:function(){var b;b=this.paths;var d=this.elem,a=d.element;b&&a?d.attr("d",c.step(b[0],b[1],this.now,this.toD)):d.attr?a&&d.attr(this.prop,this.now):(b={},b[d]=this.now+this.unit,Highcharts.css(d,b));this.options.step&&this.options.step.call(this.elem,this.now,this)},custom:function(b,c,a){var e=
13
+ this,h=function(a){return e.step(a)},f;this.startTime=+new Date;this.start=b;this.end=c;this.unit=a;this.now=this.start;this.pos=this.state=0;h.elem=this.elem;h()&&m.push(h)===1&&(q=setInterval(function(){for(f=0;f<m.length;f++)m[f]()||m.splice(f--,1);m.length||clearInterval(q)},13))},step:function(b){var c=+new Date,a;a=this.options;var e;if(this.elem.stopAnimation)a=!1;else if(b||c>=a.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();b=this.options.curAnim[this.prop]=
14
+ !0;for(e in a.curAnim)a.curAnim[e]!==!0&&(b=!1);b&&a.complete&&a.complete.call(this.elem);a=!1}else e=c-this.startTime,this.state=e/a.duration,this.pos=a.easing(e,0,1,a.duration),this.now=this.start+(this.end-this.start)*this.pos,this.update(),a=!0;return a}};this.animate=function(b,d,a){var e,h="",f,i,g;b.stopAnimation=!1;if(typeof a!=="object"||a===null)e=arguments,a={duration:e[2],easing:e[3],complete:e[4]};if(typeof a.duration!=="number")a.duration=400;a.easing=Math[a.easing]||Math.easeInOutSine;
15
+ a.curAnim=Highcharts.extend({},d);for(g in d)i=new n(b,a,g),f=null,g==="d"?(i.paths=c.init(b,b.d,d.d),i.toD=d.d,e=0,f=1):b.attr?e=b.attr(g):(e=parseFloat(HighchartsAdapter._getStyle(b,g))||0,g!=="opacity"&&(h="px")),f||(f=parseFloat(d[g])),i.custom(e,f,h)}},_getStyle:function(c,b){return window.getComputedStyle(c).getPropertyValue(b)},getScript:function(c,b){var d=l.getElementsByTagName("head")[0],a=l.createElement("script");a.type="text/javascript";a.src=c;a.onload=b;d.appendChild(a)},inArray:function(c,
16
+ b){return b.indexOf?b.indexOf(c):p.indexOf.call(b,c)},adapterRun:function(c,b){return parseInt(HighchartsAdapter._getStyle(c,b),10)},grep:function(c,b){return p.filter.call(c,b)},map:function(c,b){for(var d=[],a=0,e=c.length;a<e;a++)d[a]=b.call(c[a],c[a],a,c);return d},offset:function(c){for(var b=0,d=0;c;)b+=c.offsetLeft,d+=c.offsetTop,c=c.offsetParent;return{left:b,top:d}},addEvent:function(c,b,d){o(c).bind(b,d)},removeEvent:function(c,b,d){o(c).unbind(b,d)},fireEvent:function(c,b,d,a){var e;l.createEvent&&
17
+ (c.dispatchEvent||c.fireEvent)?(e=l.createEvent("Events"),e.initEvent(b,!0,!0),e.target=c,Highcharts.extend(e,d),c.dispatchEvent?c.dispatchEvent(e):c.fireEvent(b,e)):c.HCExtended===!0&&(d=d||{},c.trigger(b,d));d&&d.defaultPrevented&&(a=null);a&&a(d)},washMouseEvent:function(c){return c},stop:function(c){c.stopAnimation=!0},each:function(c,b){return Array.prototype.forEach.call(c,b)}}}();
@@ -0,0 +1,9 @@
1
+ function createGraphElement(elementType) {
2
+ var graphContainer = document.getElementById("graph_container");
3
+
4
+ if(graphContainer) {
5
+ var graphElement = document.createElement(elementType);
6
+ graphElement.setAttribute("id", "graph");
7
+ graphContainer.appendChild(graphElement);
8
+ }
9
+ }
@@ -1,15 +1,15 @@
1
1
  .bluff-tooltip {
2
- background: #fff;
3
- border: 1px solid #d1edf5;
4
- padding: 8px 8px 6px;
2
+ background: #fff;
3
+ border: 1px solid #d1edf5;
4
+ padding: 8px 8px 6px;
5
5
  }
6
6
  .bluff-tooltip .color {
7
- display: block;
8
- height: 4px;
9
- width: 30px;
10
- margin: 0 0 4px;
11
- overflow: hidden;
7
+ display: block;
8
+ height: 4px;
9
+ width: 30px;
10
+ margin: 0 0 4px;
11
+ overflow: hidden;
12
12
  }
13
13
  .bluff-tooltip .data {
14
- font-weight: bold;
15
- }
14
+ font-weight: bold;
15
+ }
@@ -312,6 +312,9 @@ a {
312
312
  display: block;
313
313
  margin-top: 1em;
314
314
  margin-left: 2em; }
315
+ #content div#graph {
316
+ width: 100%;
317
+ height: 600px; }
315
318
 
316
319
  a.success {
317
320
  color: #bbf8aa; }
@@ -1,10 +1,9 @@
1
1
  <html>
2
2
  <head>
3
3
  <style>
4
- <%= inline_css('css/syntax.css') %>
5
- <%= inline_css('css/bluff.css') if MetricFu.configuration.graph_engine == :bluff %>
6
- <%= inline_css('css/rcov.css') if @metrics.has_key?(:rcov) %>
4
+ <%= inline_css('css/syntax.css') %>
7
5
  </style>
6
+ <title>Analyzed File Report</title>
8
7
  </head>
9
8
  <body>
10
9
  <table cellpadding='0' cellspacing='0' class='ruby'>
@@ -27,6 +26,6 @@
27
26
  </td>
28
27
  </tr>
29
28
  <% end %>
30
- <table>
29
+ </table>
31
30
  </body>
32
31
  </html>
@@ -1,3 +1,3 @@
1
1
  module MetricFu
2
- VERSION = '4.8.0'
2
+ VERSION = '4.9.0'
3
3
  end
data/metric_fu.gemspec CHANGED
@@ -64,5 +64,6 @@ Gem::Specification.new do |s|
64
64
  s.add_development_dependency 'test_construct'
65
65
  # ensure we have a JSON parser
66
66
  s.add_development_dependency 'json'
67
+ s.add_development_dependency 'simplecov'
67
68
 
68
69
  end
@@ -0,0 +1,13 @@
1
+ class SomeClass
2
+ def method_1
3
+ 1+1
4
+ end
5
+
6
+ def method_2 ( value )
7
+ value * value
8
+ end
9
+
10
+ def method_3
11
+ "über"
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bash
2
+ which ruby
3
+ exit 0
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bash
2
+ which ruby
3
+ exit 1
@@ -67,7 +67,7 @@ describe MetricFu::Formatter::HTML do
67
67
  it "copies common javascripts to the output directory" do
68
68
  expect {
69
69
  MetricFu::Formatter::HTML.new.finish
70
- }.to create_file("#{directory('output_directory')}/bluff*.js")
70
+ }.to create_file("#{directory('output_directory')}/highcharts*.js")
71
71
  end
72
72
 
73
73
  it "creates graphs for appropriate metrics" do
@@ -118,7 +118,7 @@ describe MetricFu::Formatter::HTML do
118
118
  it "copies common javascripts to the custom output directory" do
119
119
  expect {
120
120
  MetricFu::Formatter::HTML.new(output: @output).finish
121
- }.to create_file("#{directory('base_directory')}/#{@output}/bluff*.js")
121
+ }.to create_file("#{directory('base_directory')}/#{@output}/highcharts*.js")
122
122
  end
123
123
 
124
124
  it "creates graphs for appropriate metrics in the custom output directory " do
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+ require 'simplecov'
3
+ require 'metric_fu/metrics/rcov/simplecov_formatter'
4
+
5
+ describe SimpleCov::Formatter::MetricFu do
6
+ before do
7
+ @rcov_file = subject.coverage_file_path
8
+ File.delete( @rcov_file ) if File.exists?( @rcov_file )
9
+
10
+ @result = SimpleCov::Result.new(
11
+ {
12
+ FIXTURE.fixtures_path.join('coverage.rb').expand_path.to_s =>
13
+ [1,1,1,1,nil,1,0,1,1,nil,0,1,1]
14
+ }
15
+ )
16
+
17
+ # Set to default encoding
18
+ Encoding.default_internal = nil if defined?(Encoding)
19
+ end
20
+
21
+ it "test_format" do
22
+ SimpleCov::Formatter::MetricFu.new.format( @result )
23
+
24
+ expect(File.exists?( @rcov_file )).to be_truthy
25
+ end
26
+
27
+ it "test_encoding" do
28
+ # This is done in many rails environments
29
+ Encoding.default_internal = 'UTF-8' if defined?(Encoding)
30
+
31
+ SimpleCov::Formatter::MetricFu.new.format( @result )
32
+ end
33
+
34
+ it "test_create_content" do
35
+ content = SimpleCov::Formatter::MetricFu::FormatLikeRCov.new(@result).format
36
+ test = "\="*80
37
+
38
+ expect(content).to match(/#{test}/)
39
+ expect(content).to match(/!! value \* value/)
40
+ end
41
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,27 +1,26 @@
1
- require 'rspec/autorun'
2
-
1
+ # add lib to the load path just like rubygems does
2
+ $:.unshift File.expand_path("../../lib", __FILE__)
3
3
  if ENV['COVERAGE']
4
4
  require 'simplecov'
5
5
  formatters = [SimpleCov::Formatter::HTMLFormatter]
6
6
  begin
7
7
  puts '[COVERAGE] Running with SimpleCov HTML Formatter'
8
- require 'simplecov-rcov-text'
9
- formatters << SimpleCov::Formatter::RcovTextFormatter
10
- puts '[COVERAGE] Running with SimpleCov Rcov Formatter'
8
+ require 'metric_fu/metrics/rcov/simplecov_formatter'
9
+ formatters << SimpleCov::Formatter::MetricFu
10
+ puts '[COVERAGE] Running with SimpleCov MetricFu Formatter'
11
11
  rescue LoadError
12
- puts '[COVERAGE] SimpleCov Rcov formatter could not be loaded'
12
+ puts '[COVERAGE] SimpleCov MetricFu formatter could not be loaded'
13
13
  end
14
14
  SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[ *formatters ]
15
15
  SimpleCov.start
16
16
  end
17
17
 
18
+ require 'rspec/autorun'
18
19
  require 'date'
19
20
  require 'test_construct'
20
21
  require 'json'
21
22
  require 'pry-nav'
22
23
 
23
- # add lib to the load path just like rubygems does
24
- $:.unshift File.expand_path("../../lib", __FILE__)
25
24
  require 'metric_fu'
26
25
  include MetricFu
27
26
  def mf_log(msg); mf_debug(msg); end
@@ -0,0 +1,134 @@
1
+ # usage_test = UsageTest.new
2
+ # usage_test.test_files(EXAMPLE_FILES)
3
+
4
+ # puts "SUCCESS!"
5
+ # Process.exit! 0
6
+ require 'metric_fu/logging/mf_debugger'
7
+ require 'open3'
8
+ class UsageTest
9
+ def initialize
10
+ @markdown = Redcarpet::Markdown.new(HTMLRenderAndVerifyCodeBlocks, :fenced_code_blocks => true)
11
+ end
12
+
13
+ def test_files(paths)
14
+ in_test_directory do
15
+ Array(paths).each do |path|
16
+ puts "Testing #{path}"
17
+ @markdown.render(File.read(path))
18
+ puts
19
+ end
20
+ end
21
+ puts "SUCCESS!"
22
+ Process.exit! 0
23
+ end
24
+
25
+ private
26
+
27
+ def in_test_directory
28
+ Dir.mktmpdir do |dir|
29
+ Dir.chdir(dir) {
30
+ `git init; touch README; git add README; git commit -m 'first'`
31
+ yield
32
+ }
33
+ end
34
+ end
35
+ end
36
+ SnippetRunner = Struct.new(:code, :language) do
37
+ include MfDebugger
38
+ SystemCommandError = Class.new(StandardError)
39
+ TestResult = Struct.new(:success, :captured_output)
40
+
41
+ def test!
42
+ time = Time.now
43
+ test_result = run_code
44
+ mf_debug "#{Time.now - time} seconds"
45
+ if test_result.success
46
+ print '.'
47
+ else
48
+ puts 'x'
49
+ puts "Red :( language: #{language}, code #{code}, #{test_result.captured_output}"
50
+ Process.exit! 1
51
+ end
52
+ end
53
+
54
+ def run_code(test_result = TestResult.new(:no_result,''))
55
+ test_result.captured_output = case language
56
+ when 'ruby' then eval_ruby
57
+ when 'sh' then run_system_command
58
+ else mf_debug "Cannot test language: #{language.inspect}"
59
+ end
60
+ test_result.success = true
61
+ test_result
62
+ rescue StandardError => run_error
63
+ test_result.captured_output = exception_message(run_error)
64
+ test_result.success = false
65
+ test_result
66
+ rescue SystemExit => system_exit
67
+ puts "I am a system exit"
68
+ test_result.captured_output = exception_message(system_exit)
69
+ test_result.success = system_exit.success?
70
+ test_result
71
+ end
72
+
73
+ def eval_ruby(fail_on_empty=false)
74
+ capture_output(fail_on_empty) do
75
+ instance_eval(code)
76
+ end
77
+ end
78
+
79
+ def run_system_command(fail_on_empty=true)
80
+ out = ''
81
+ err = ''
82
+ pid = :not_set
83
+ exit_status = :not_set
84
+ Open3.popen3(code) do |stdin, stdout, stderr, wait_thr|
85
+ out << stdout.read.chomp
86
+ err << stderr.read.chomp
87
+ pid = wait_thr.pid
88
+ exit_status = wait_thr.value
89
+ end
90
+ exit_code = exit_status.exitstatus
91
+ case exit_code
92
+ when 0 then "Ran with exit status #{exit_code}"
93
+ when (1..Float::INFINITY) then fail SystemCommandError.new("Failed with exit status #{exit_code}. #{err}----#{out}")
94
+ else fail SystemCommandError.new("Execution failed with exit status #{exit_code}. #{err}----#{out}")
95
+ end
96
+
97
+ end
98
+
99
+ def exception_message(e)
100
+ "#{e.class}\t#{e.message}"
101
+ end
102
+
103
+ def capture_output(fail_on_empty)
104
+ exception = nil
105
+ stderr = :not_set
106
+ stdout = :not_set
107
+ MfDebugger::Logger.capture_output(STDOUT) do
108
+ stdout =
109
+ MfDebugger::Logger.capture_output(STDERR) do
110
+ begin
111
+ stderr = yield
112
+ rescue Exception => e
113
+ exception = e
114
+ end
115
+ end
116
+ end
117
+ if [nil, '', :not_set].none? {|c| c == stderr }
118
+ mf_debug "Captured STDERR"
119
+ stderr
120
+ elsif [nil, '', :not_set].none? {|c| c == stdout }
121
+ mf_debug "Captured STDOUT"
122
+ stdout
123
+ elsif exception
124
+ mf_debug "Captured Exception"
125
+ raise exception
126
+ else
127
+ mf_debug "Captured Nothing"
128
+ if fail_on_empty
129
+ fail SystemCommandError.new 'No output generated or exception caught'
130
+ end
131
+ end
132
+ end
133
+
134
+ end
@@ -0,0 +1,69 @@
1
+ describe 'usage test' do
2
+ ROOT_PATH = File.expand_path("..", File.dirname(__FILE__))
3
+ require File.join(ROOT_PATH, 'spec/support/usage_test')
4
+
5
+ context 'evaluating ruby code' do
6
+ specify 'succeeds when the code runs without errors' do
7
+ code = "1 + 1"
8
+ test_result = SnippetRunner.new(code, 'ruby').run_code
9
+ expect(test_result.captured_output).to eq(2)
10
+ expect(test_result.success).to eq(true)
11
+ end
12
+ specify 'fails when the code raises a standard error' do
13
+ code = "fail NameError.new('no name')"
14
+ test_result = SnippetRunner.new(code, 'ruby').run_code
15
+ expect(test_result.captured_output).to match('NameError')
16
+ expect(test_result.captured_output).to match('no name')
17
+ expect(test_result.success).to eq(false)
18
+ end
19
+ specify 'succeeds when the code exits with a zero exit status' do
20
+ code = "puts 1 + 1; exit 0"
21
+ test_result = SnippetRunner.new(code, 'ruby').run_code
22
+ expect(test_result.captured_output).to match('SystemExit')
23
+ expect(test_result.success).to eq(true)
24
+ end
25
+ specify 'fails when the code exits with a non-zero exit status' do
26
+ code = "puts 1 + 1; exit 1"
27
+ test_result = SnippetRunner.new(code, 'ruby').run_code
28
+ expect(test_result.captured_output).to match('SystemExit')
29
+ expect(test_result.success).to eq(false)
30
+ end
31
+
32
+ end
33
+ context 'evaluating shell commands' do
34
+ specify 'succeeds when the command runs without errors' do
35
+ code = "which ruby"
36
+ test_result = SnippetRunner.new(code, 'sh').run_code
37
+ expect(test_result.captured_output).to match("exit status 0")
38
+ expect(test_result.success).to eq(true)
39
+ end
40
+ specify 'fails when the command runs with an error' do
41
+ code = "sandwhich_fu ruby"
42
+ test_result = SnippetRunner.new(code, 'sh').run_code
43
+ expect(test_result.captured_output).to match(failed_command_error)
44
+ expect(test_result.success).to eq(false)
45
+ end
46
+ specify 'succeeds when the code exits with a zero exit status' do
47
+ code = "sh #{fixtures_path.join('exit0.sh').to_path}"
48
+ test_result = SnippetRunner.new(code, 'sh').run_code
49
+ expect(test_result.captured_output).to match("exit status 0")
50
+ expect(test_result.success).to eq(true)
51
+ end
52
+ specify 'fails when the code exits with a non-zero exit status' do
53
+ code = "sh #{fixtures_path.join('exit1.sh').to_path}"
54
+ test_result = SnippetRunner.new(code, 'sh').run_code
55
+ expect(test_result.captured_output).to match("exit status 1")
56
+ expect(test_result.success).to eq(false)
57
+ end
58
+
59
+ end
60
+
61
+ def failed_command_error
62
+ defined?(JRUBY_VERSION) ? 'IOError' : 'Errno::ENOENT'
63
+ end
64
+
65
+ def fixtures_path
66
+ fixtures_dir = File.join(File.expand_path('..', File.dirname(__FILE__)), 'spec', 'fixtures')
67
+ Pathname(fixtures_dir)
68
+ end
69
+ end