assert-view 0.1.0 → 0.2.0

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/Gemfile.lock CHANGED
@@ -1,15 +1,18 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- assert-view (0.1.0)
4
+ assert-view (0.2.0)
5
+ undies (~> 1.1)
5
6
 
6
7
  GEM
7
8
  remote: http://rubygems.org/
8
9
  specs:
9
10
  ansi (1.3.0)
10
- assert (0.3.0)
11
+ assert (0.4.0)
11
12
  ansi (~> 1.3)
13
+ assert-view
12
14
  rake (0.9.2)
15
+ undies (1.1.0)
13
16
 
14
17
  PLATFORMS
15
18
  ruby
data/assert-view.gemspec CHANGED
@@ -19,4 +19,6 @@ Gem::Specification.new do |s|
19
19
 
20
20
  s.add_development_dependency("bundler")
21
21
  s.add_development_dependency("assert")
22
+
23
+ s.add_dependency("undies", ["~> 1.1"])
22
24
  end
@@ -1,4 +1,5 @@
1
1
  require 'assert/options'
2
+ require 'assert/view/renderer'
2
3
 
3
4
  module Assert::View
4
5
 
@@ -12,49 +13,103 @@ module Assert::View
12
13
  default_errored_abbrev 'E'
13
14
  end
14
15
 
15
- attr_reader :suite
16
+ # the Renderer defines the hooks and callbacks needed for the runner to
17
+ # work with the view. It provides:
18
+ # * 'render': called by the runner to render the view
19
+ # * 'self.helper': used to provide helper mixins to the renderer template
20
+ include Renderer
21
+
22
+ attr_accessor :suite, :output_io, :runtime_result_callback
16
23
 
17
24
  def initialize(output_io, suite=Assert.suite)
18
- @suite = suite
19
- @out = output_io
25
+ self.suite = suite
26
+ self.output_io = output_io
20
27
  end
21
28
 
22
- # override this to define how a view calls the runner and renders its results
23
- def render(*args, &runner)
29
+ def view
30
+ self
24
31
  end
25
32
 
26
- def handle_runtime_result(result)
33
+
34
+
35
+ # TODO: look for files in the .assert dir
36
+ # TODO: allow option for specifying which template to use
37
+ # TODO: test
38
+ def template_file
39
+ File.expand_path("./templates/#{self.options.template}.rb", File.dirname(__FILE__))
27
40
  end
28
41
 
29
- protected
30
42
 
31
- def io_puts(msg, opts={})
32
- @out.puts(io_msg(msg, opts={}))
43
+
44
+ # called by the view template
45
+ # store off any result_callback
46
+ # call the runner callback to actually run the tests
47
+ def run_tests(runner_callback, &result_callback)
48
+ self.runtime_result_callback = result_callback
49
+ runner_callback.call if runner_callback
33
50
  end
34
51
 
35
- def io_print(msg, opts={})
36
- @out.print(io_msg(msg, opts={}))
52
+ # callback used by the runner to notify the view of any new results
53
+ # pipes the runtime result to any result callback block
54
+ def handle_runtime_result(result)
55
+ self.runtime_result_callback.call(result) if self.runtime_result_callback
37
56
  end
38
57
 
58
+ # get the formatted suite run time
39
59
  def run_time(format='%.6f')
40
- format % @suite.run_time
60
+ format % self.suite.run_time
41
61
  end
42
62
 
43
63
  def runner_seed
44
- @suite.runner_seed
64
+ self.suite.runner_seed
45
65
  end
46
66
 
47
67
  def count(type)
48
- @suite.count(type)
68
+ self.suite.count(type)
69
+ end
70
+
71
+ # TODO: test
72
+ def tests?
73
+ self.count(:tests) > 0
74
+ end
75
+
76
+ def all_passed?
77
+ self.count(:passed) == self.count(:results)
49
78
  end
50
79
 
51
- private
80
+ # return a list of result symbols that have actually occurred
81
+ def ocurring_result_types
82
+ @result_types ||= [
83
+ :passed, :failed, :ignored, :skipped, :errored
84
+ ].select { |result_sym| self.count(result_sym) > 0 }
85
+ end
86
+
87
+ # print a result summary message for a given result type
88
+ def result_summary_msg(result_type)
89
+ if result_type == :passed && self.all_passed?
90
+ self.all_passed_result_summary_msg
91
+ else
92
+ "#{self.count(result_type)} #{result_type.to_s}"
93
+ end
94
+ end
95
+
96
+ # generate an appropriate result summary msg for all tests passing
97
+ def all_passed_result_summary_msg
98
+ if self.count(:results) < 1
99
+ "uhh..."
100
+ elsif self.count(:results) == 1
101
+ "it passed"
102
+ else
103
+ "all passed"
104
+ end
105
+ end
52
106
 
53
- def io_msg(msg, opts={})
54
- if msg.kind_of?(::Symbol) && self.respond_to?(msg)
55
- self.send(msg).to_s
107
+ # generate a comma-seperated sentence fragment given a list of things
108
+ def to_sentence(things)
109
+ if things.size <= 2
110
+ things.join(things.size == 2 ? ' and ' : '')
56
111
  else
57
- msg.to_s
112
+ [things[0..-2].join(", "), things.last].join(", and ")
58
113
  end
59
114
  end
60
115
 
@@ -0,0 +1,25 @@
1
+ require 'ansi/code'
2
+
3
+ module Assert::View::Helpers
4
+
5
+ module AnsiStyles
6
+
7
+ def result_ansi_styles(result)
8
+ view.options.styled ? view.options.send("#{result.to_sym}_styles") : []
9
+ end
10
+
11
+ def ansi_styled_msg(msg, styles=[])
12
+ if !(style = ansi_style(*styles)).empty?
13
+ style + msg + ANSI.send(:reset)
14
+ else
15
+ msg
16
+ end
17
+ end
18
+
19
+ def ansi_style(*ansi_codes)
20
+ ansi_codes.collect{|code| ANSI.send(code) rescue nil}.compact.join('')
21
+ end
22
+
23
+ end
24
+
25
+ end
@@ -0,0 +1,45 @@
1
+ require 'undies'
2
+
3
+ module Assert::View
4
+
5
+ # this module is mixed in to the Assert::View::Base class
6
+ # it use Undies to define and render view templates
7
+ module Renderer
8
+
9
+ def self.included(receiver)
10
+ receiver.send(:extend, ClassMethods)
11
+ end
12
+
13
+ # define rendering template class to use for rendering
14
+ # need to overwrite the '_' and '__' meths to add trailing newlines
15
+ # b/c streaming output doesn't add any whitespace
16
+ class Template < ::Undies::Template
17
+
18
+ def _(data="", nl=true); super(data.to_s + (nl ? "\n" : "")); end
19
+ def __(data="", nl=true); super(data.to_s + (nl ? "\n" : "")); end
20
+
21
+ end
22
+
23
+ # this method is required by assert and is called by the test runner
24
+ # use Undies to render the template
25
+ # using the view's template file
26
+ # streaming to the view's output io
27
+ # passing in the view itself and any runner_callback as locals
28
+ def render(*args, &runner_callback)
29
+ Template.new(File.expand_path(self.template_file), self.output_io, {
30
+ :view => self,
31
+ :runner => runner_callback
32
+ })
33
+ end
34
+
35
+ module ClassMethods
36
+
37
+ # make any helper methods available to the template
38
+ def helper(helper_klass)
39
+ Template.send(:include, helper_klass)
40
+ end
41
+
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,36 @@
1
+ __
2
+ __ view.loaded_tests_statement
3
+
4
+ if view.tests?
5
+
6
+ __ view.running_tests_statement
7
+
8
+ view.run_tests(runner) do |each_result|
9
+ result_sym = each_result.to_sym
10
+ result_abbrev = view.options.send("#{result_sym}_abbrev")
11
+ __ ansi_styled_msg(result_abbrev, result_ansi_styles(result_sym)), false
12
+ end
13
+ __ "\n" # add a newline after streamed runner output
14
+
15
+ view.detailed_results do |result, output|
16
+ __ ansi_styled_msg(result.to_s, result_ansi_styles(result))
17
+
18
+ if !output.empty?
19
+ __ view.result_output_start_msg
20
+ __ output, false
21
+ __ view.result_output_end_msg
22
+ end
23
+
24
+ __
25
+ end
26
+
27
+ end
28
+
29
+ # build a summary sentence w/ styled results breakdown
30
+ styled_results_breakdown_statement = view.results_breakdown_statement do |msg, result_type|
31
+ ansi_styled_msg(msg, result_ansi_styles(result_type))
32
+ end
33
+
34
+ __ [ view.result_count_statement, ": ", styled_results_breakdown_statement ].join('')
35
+ __
36
+ __ view.run_time_statement
@@ -1,129 +1,64 @@
1
- require 'assert/view/base'
2
1
  require 'assert/result'
3
-
4
- require 'ansi/code'
2
+ require 'assert/options'
3
+ require 'assert/view/base'
5
4
 
6
5
  module Assert::View
7
6
 
8
7
  class Terminal < Base
9
8
 
10
- options do
11
- default_styled false
12
- default_passed_styles :green
13
- default_failed_styles :red, :bold
14
- default_errored_styles :yellow, :bold
15
- default_skipped_styles :cyan
16
- default_ignored_styles :magenta
17
- end
18
-
19
- def render(*args, &runner)
20
- self.io_puts(:load_stmt)
21
-
22
- if count(:tests) > 0
23
- self.io_puts(:run_stmt)
24
- runner.call if runner
25
- self.io_puts(:detailed_results)
26
- end
27
-
28
- self.io_puts(:results_stmt)
9
+ def loaded_tests_statement
10
+ "Loaded suite (#{view.count(:tests)} test#{'s' if view.count(:tests) != 1})"
29
11
  end
30
12
 
31
- def handle_runtime_result(result)
32
- sym = result.to_sym
33
- self.io_print(result_io_msg(self.options.send("#{sym}_abbrev"), sym))
34
- end
35
-
36
- protected
37
-
38
- def load_stmt
39
- tplur = (tcount = count(:tests)) == 1 ? "test": "tests"
40
- "\nLoaded suite (#{tcount} #{tplur})"
13
+ def running_tests_statement
14
+ "Running tests in random order, seeded with: \"#{self.runner_seed}\""
41
15
  end
42
16
 
43
- def run_stmt
44
- "Running tests in random order, seed: '#{self.runner_seed}'"
17
+ # show test details in reverse order from how they were collected (FILO)
18
+ def detailed_tests
19
+ @detailed_tests ||= self.suite.ordered_tests.reverse
45
20
  end
46
21
 
47
- def detailed_results
48
- details = self.suite.ordered_tests.reverse.collect do |test|
49
- test.results.collect do |result|
50
- if show_result_details?(result)
51
- [ result_io_msg(result.to_s, result.to_sym),
52
- output_io_msg(test.output.to_s)
53
- ].join("\n")
54
- end
55
- end
56
- end.flatten.compact
57
- "\n\n" + details.join("\n\n") if !details.empty?
22
+ # get all the results that have details to show
23
+ # in addition, if a block is given...
24
+ # yield each result with its test output
25
+ def detailed_results(test=nil)
26
+ tests = test.nil? ? self.detailed_tests : [test]
27
+ tests.collect do |test|
28
+ test.results.
29
+ select { |result| self.show_result_details?(result) }.
30
+ each {|r| yield r, test.output if block_given?}
31
+ end.compact.flatten
58
32
  end
59
33
 
60
- def results_stmt
61
- rplur = (rcount = count(:results)) == 1 ? "result" : "results"
62
- [ "\n",
63
- "#{rcount} test #{rplur}: ", results_breakdown, "\n\n",
64
- "(#{self.run_time} seconds)"
65
- ].join('')
34
+ # only show result details for failed or errored results
35
+ # show result details if a skip or passed result was issues w/ a message
36
+ def show_result_details?(result)
37
+ ([:failed, :errored].include?(result.to_sym)) ||
38
+ ([:skipped, :ignored].include?(result.to_sym) && result.message)
66
39
  end
67
40
 
68
- def results_breakdown
69
- if count(:passed) == count(:results)
70
- stmnt = if count(:results) < 1
71
- "uhh..."
72
- elsif count(:results) == 1
73
- "it passed"
74
- else
75
- "all passed"
76
- end
77
- result_io_msg(stmnt, :passed)
78
- else
79
- breakdowns = [:passed, :failed, :ignored, :skipped, :errored]
80
- breakdowns = breakdowns.inject([]) do |results, result_sym|
81
- results << (if count(result_sym) > 0
82
- result_io_msg("#{count(result_sym)} #{result_sym}", result_sym)
83
- end)
84
- end.compact
85
- if breakdowns.size < 2
86
- breakdowns.join('')
87
- elsif breakdowns.size == 2
88
- breakdowns.join(" and ")
89
- else
90
- [breakdowns[0..-2].join(", "), breakdowns.last].join(", and ")
91
- end
92
- end
41
+ def result_output_start_msg
42
+ "--- stdout ---"
93
43
  end
94
-
95
- def result_io_msg(msg, result_sym)
96
- term_styles = if self.options.styled
97
- self.options.send("#{result_sym}_styles")
98
- end
99
- io_msg(msg, :term_styles => term_styles)
44
+ def result_output_end_msg
45
+ "--------------"
100
46
  end
101
47
 
102
- def output_io_msg(output)
103
- if output && !output.empty?
104
- [ "--- stdout ---",
105
- io_msg(output),
106
- "--------------"
107
- ].collect{|i| i.strip}.join("\n")
108
- end
48
+ # generate a sentence fragment describing the breakdown of test results
49
+ # if a block is given, yield each msg in the breakdown for custom template formatting
50
+ def results_breakdown_statement
51
+ self.to_sentence(self.ocurring_result_types.collect do |result_type|
52
+ yield(self.result_summary_msg(result_type), result_type) if block_given?
53
+ end)
109
54
  end
110
55
 
111
- def io_msg(msg, opts={})
112
- val = super
113
- if !(style = term_style(*opts[:term_styles])).empty?
114
- val = style + val + ANSI.send(:reset)
115
- else
116
- val
117
- end
56
+ def result_count_statement
57
+ "#{self.count(:results)} test result#{'s' if self.count(:results) != 1}"
118
58
  end
119
59
 
120
- def term_style(*ansi_codes)
121
- ansi_codes.collect{|code| ANSI.send(code) rescue nil}.compact.join('')
122
- end
123
-
124
- def show_result_details?(result)
125
- ([:failed, :errored].include?(result.to_sym)) ||
126
- ([:skipped, :ignored].include?(result.to_sym) && result.message)
60
+ def run_time_statement
61
+ "(#{self.run_time} seconds)"
127
62
  end
128
63
 
129
64
  end
@@ -1,5 +1,5 @@
1
1
  module Assert; end
2
2
 
3
3
  module Assert::View
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/assert/view.rb CHANGED
@@ -1,2 +1,2 @@
1
1
  module Assert; end
2
- module Assert::Views; end
2
+ module Assert::View; end
data/test/base_test.rb CHANGED
@@ -7,16 +7,26 @@ require 'stringio'
7
7
  module Assert::View
8
8
 
9
9
  class BaseTest < Assert::Context
10
- desc "the view base"
10
+ desc "the base view"
11
11
  setup do
12
12
  @view = Assert::View::Base.new(Assert::Suite.new, StringIO.new("", "w+"))
13
13
  end
14
14
  subject{ @view }
15
15
 
16
- should have_reader :suite
17
- should have_instance_methods :render, :handle_runtime_result, :options
16
+ should have_accessors :suite, :output_io, :runtime_result_callback
17
+ should have_instance_methods :template_file, :run_tests, :handle_runtime_result
18
+ should have_instance_methods :run_time, :runner_seed, :count, :tests?, :all_passed?
19
+ should have_instance_methods :ocurring_result_types, :result_summary_msg
20
+ should have_instance_methods :all_passed_result_summary_msg, :to_sentence
21
+
22
+ # options stuff
23
+ should have_instance_method :options
18
24
  should have_class_method :options
19
25
 
26
+ # renderer stuff
27
+ should have_instance_method :render
28
+ should have_class_method :helper
29
+
20
30
  end
21
31
 
22
32
  class BaseOptionsTest < Assert::Context
@@ -39,6 +49,4 @@ module Assert::View
39
49
 
40
50
  end
41
51
 
42
-
43
-
44
52
  end
@@ -1,32 +1,22 @@
1
1
  require 'assert'
2
- require 'assert/options'
3
2
 
4
3
  require 'assert/view/terminal'
4
+ require 'stringio'
5
5
 
6
6
  module Assert::View
7
7
 
8
- class TerminalOptionsTest < Assert::Context
9
- desc "options for the terminal view"
10
- subject do
11
- Assert::View::Terminal.options
8
+ class TerminalTest < Assert::Context
9
+ desc "the terminal view"
10
+ setup do
11
+ @view = Assert::View::Terminal.new(Assert::Suite.new, StringIO.new("", "w+"))
12
12
  end
13
+ subject{ @view }
13
14
 
14
- should "be an Options::Base object" do
15
- assert_kind_of Assert::Options::Base, subject
16
- end
17
-
18
- should "default the styled option" do
19
- assert_equal false, subject.default_styled
20
- end
21
-
22
- should "default its result styles" do
23
- assert_equal :green, subject.default_passed_styles
24
- assert_equal [:red, :bold], subject.default_failed_styles
25
- assert_equal :magenta, subject.default_ignored_styles
26
- assert_equal :cyan, subject.default_skipped_styles
27
- assert_equal [:yellow, :bold], subject.default_errored_styles
28
- end
15
+ should have_instance_methods :loaded_tests_statement, :running_tests_statement
16
+ should have_instance_methods :detailed_tests, :detailed_results, :show_result_details?
17
+ should have_instance_methods :result_output_start_msg, :result_output_end_msg
18
+ should have_instance_methods :results_breakdown_statement, :result_count_statement
19
+ should have_instance_methods :run_time_statement
29
20
 
30
21
  end
31
-
32
22
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: assert-view
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 1
8
+ - 2
9
9
  - 0
10
- version: 0.1.0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Kelly Redding
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-08-31 00:00:00 Z
18
+ date: 2011-09-08 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  type: :development
@@ -45,6 +45,21 @@ dependencies:
45
45
  version: "0"
46
46
  version_requirements: *id002
47
47
  name: assert
48
+ - !ruby/object:Gem::Dependency
49
+ type: :runtime
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ~>
55
+ - !ruby/object:Gem::Version
56
+ hash: 13
57
+ segments:
58
+ - 1
59
+ - 1
60
+ version: "1.1"
61
+ version_requirements: *id003
62
+ name: undies
48
63
  description: A collection of views for use in the Assert testing framework
49
64
  email:
50
65
  - kelly@kelredd.com
@@ -63,6 +78,9 @@ files:
63
78
  - assert-view.gemspec
64
79
  - lib/assert/view.rb
65
80
  - lib/assert/view/base.rb
81
+ - lib/assert/view/helpers/ansi.rb
82
+ - lib/assert/view/renderer.rb
83
+ - lib/assert/view/templates/assert.ansi.rb
66
84
  - lib/assert/view/terminal.rb
67
85
  - lib/assert/view/version.rb
68
86
  - test/base_test.rb