pork 1.5.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cc7cc07abd9d5e467ea5e229953b9bfd4ecc0978
4
- data.tar.gz: adec072a9ef317b4f6baad7e38d14b96ee33aea2
3
+ metadata.gz: 66af2258263479b7c9b46d32d87dab94300c86c7
4
+ data.tar.gz: dd01950d9a7026886e35b48054c97c5f69f6e6fa
5
5
  SHA512:
6
- metadata.gz: 9c181fef0d0491353d1034fb852f434c148eaaf6142f4d536320ee2c1f74a23e59a019340c8202399984ee75cebdee71bb545914558c895fd45dfbc675a0f7c6
7
- data.tar.gz: c5e3d773b083eb21700a089a122cc577143a42e26c98c37ed8ed901b73d171b5b7717d8dd67a5fbecbdd67c030fe64057299698b212ece295421907f9e30f3b1
6
+ metadata.gz: '0584b1e173a3d0190b28ebfddba0475ff9e47e85d51081a8f5401f789f8ee1e7aa3cd1680efd58d0fd44d4e444fecc567fcec86ca13fa66eb6525baeeb29dd58'
7
+ data.tar.gz: 5705b43ac037712e230b6249f41f1ff12a1347e23a1bdf84632603878910ecf6f9d9a2e9c9e1c0400ea953453a232874caadb5694c8577b6b3a9220b3f45ee16
@@ -1,9 +1,8 @@
1
1
  sudo: false
2
2
  language: ruby
3
3
  rvm:
4
- - 2.1
5
- - 2.2
6
- - 2.3.0
4
+ - 2.2.5
5
+ - 2.3.1
7
6
  - rbx
8
7
  - jruby-9
9
8
 
data/CHANGES.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # CHANGES
2
2
 
3
+ ## Pork 2.0.0 -- 2016-09-10
4
+
5
+ ### Incompatible changes
6
+
7
+ * `Pork::Executor` is now renamed to `Pork::Suite`, and the new
8
+ `Pork::Executor` would be served as the real executor who's responsible
9
+ for running the test suites!
10
+ * `Pork::Executor.execute` would now take a hash as the argument.
11
+ * `Pork::Suite.after` would now run in a reverse manner because that would
12
+ serve better as a destructor.
13
+
14
+ ### Enhancement
15
+
16
+ * `Pork::Suite.desc` would now preserve the original argument being passed to
17
+ `Pork::Suite.describe`, rather than converting it to a string.
18
+ * Major internal structure cleanup. Now we don't include everything into the
19
+ context, but use different objects to do different things. For example,
20
+ now we have `Pork::Isolator` to isolate the context.
21
+ * Introduced `Pork.execute_extensions` which would be extending to
22
+ `Pork::Executor`. The only extension for it for now is `Pork::Should`.
23
+ * Don't crash if `Pork.loaded` was never called.
24
+ * Now you could also make assertions in `after` block without triggering
25
+ `Missing assertions` errors.
26
+
3
27
  ## Pork 1.5.0 -- 2016-03-10
4
28
 
5
29
  ### Enhancement
data/README.md CHANGED
@@ -93,7 +93,7 @@ end
93
93
 
94
94
  describe 'C' do
95
95
  # Also, we're not forced to include something in all describe blocks.
96
- # If we want, we could do this instead: `Pork::Executor.include(Module.new)`
96
+ # If we want, we could do this instead: `Pork::Suite.include(Module.new)`
97
97
  # That would be the same as including in `Bacon::Context`
98
98
  would 'not respond_to? in_module nor in_describe' do
99
99
  should.not.respond_to?(:in_module)
@@ -298,7 +298,7 @@ Pork.autorun
298
298
 
299
299
  Here it `require 'pork/should'`, and it would load the monkey patches for
300
300
  inserting `Kernel#should` shown in SYNOPSIS. This is actually optional,
301
- and could be replaced with `Pork::Executor#expect`. For example, we could
301
+ and could be replaced with `Pork::Suite#expect`. For example, we could
302
302
  also write it this way:
303
303
 
304
304
  ``` ruby
@@ -580,16 +580,16 @@ So this creates a test suite which should be containing various test cases
580
580
  suite, which accepts anything could be converted to a string. The _default_
581
581
  description is `:default` (which would be converted to `'default: '`)
582
582
 
583
- Each `describe` block would create a new subclass of `Pork::Executor` for
583
+ Each `describe` block would create a new subclass of `Pork::Suite` for
584
584
  isolating test suites. Each nested `describe` block would be a subclass of
585
- its parent `Pork::Executor`.
585
+ its parent `Pork::Suite`.
586
586
 
587
587
  ``` ruby
588
588
  require 'pork/auto'
589
589
 
590
590
  describe do
591
591
  would 'be default: for the default description' do
592
- self.class.desc.should.eq 'default: '
592
+ self.class.desc.should.eq :default
593
593
  end
594
594
  end
595
595
  ```
@@ -602,7 +602,7 @@ description of the test case, which accepts anything could be converted to
602
602
  a string. The _default_ description is also `:default`.
603
603
 
604
604
  Each `would` block would be run inside a new instance of the describing
605
- `Pork::Executor` to isolate instance variables.
605
+ `Pork::Suite` to isolate instance variables.
606
606
 
607
607
  ### Pork::API.before
608
608
 
@@ -637,20 +637,21 @@ end
637
637
  Each `after` block would be called after each `would` block (test case).
638
638
  You would probably want to cleanup stuffs inside `after` blocks.
639
639
 
640
- Each nested `describe` would also run parents' `after` block as well.
640
+ Note that each nested `describe` would also run parents' `after` block in a
641
+ reverse manner as opposed to `before`.
641
642
 
642
643
  ``` ruby
643
644
  require 'pork/auto'
644
645
 
645
646
  describe do
646
647
  after do
647
- @a.should.eq 1
648
- @a += 1
648
+ @a.should.eq 2
649
649
  end
650
650
 
651
651
  describe do
652
652
  after do
653
- @a.should.eq 2
653
+ @a.should.eq 1
654
+ @a += 1
654
655
  end
655
656
 
656
657
  would do
@@ -694,7 +695,7 @@ describe do
694
695
  end
695
696
  ```
696
697
 
697
- ### Pork::Executor#expect
698
+ ### Pork::Suite#expect
698
699
 
699
700
  It is the core of `Kernel#should`. Think of:
700
701
 
@@ -720,7 +721,7 @@ is equivalent to:
720
721
  expect(object, 'message').eq(1)
721
722
  ```
722
723
 
723
- ### Pork::Executor#skip
724
+ ### Pork::Suite#skip
724
725
 
725
726
  At times we might want to skip some tests while leave the codes there without
726
727
  removing them or commenting them out. This is where `skip` would be helpful.
@@ -735,7 +736,7 @@ describe do
735
736
  end
736
737
  ```
737
738
 
738
- ### Pork::Executor#ok
739
+ ### Pork::Suite#ok
739
740
 
740
741
  Because Pork would complain if a test case does not have any assertions,
741
742
  sometimes we might want to tell Pork that it's ok because we've already
@@ -758,7 +759,7 @@ describe do
758
759
  end
759
760
  ```
760
761
 
761
- ### Pork::Executor#flunk
762
+ ### Pork::Suite#flunk
762
763
 
763
764
  If we're writing program carefully, there are a few cases where a condition
764
765
  would never meet. We could `raise "IMPOSSIBLE"` or we could simply call
data/TODO.md CHANGED
@@ -1,5 +1,3 @@
1
1
 
2
2
  * introduce configs
3
- * plugin: color/reverse backtrace, replicating command, inspect mode
4
3
  * executable
5
- * if it's executing from a copy block, run all pasted blocks
@@ -1,17 +1,9 @@
1
1
 
2
+ require 'pork/api'
3
+ require 'pork/stat'
2
4
  require 'pork/executor'
3
5
 
4
6
  module Pork
5
- module API
6
- module_function
7
- def before █ Executor.before(&block); end
8
- def after █ Executor.after( &block); end
9
- def copy desc=:default, █ Executor.copy( desc, &block); end
10
- def paste desc=:default, *args ; Executor.paste( desc, *args ); end
11
- def describe desc=:default, &suite; Executor.describe(desc, &suite); end
12
- def would desc=:default, &test ; Executor.would( desc, &test ); end
13
- end
14
-
15
7
  # default to :shuffled while eliminating warnings for uninitialized ivar
16
8
  def self.execute_mode mode=nil
17
9
  @execute_mode = mode || @execute_mode ||= :shuffled
@@ -31,6 +23,10 @@ module Pork
31
23
  @report_extensions ||= []
32
24
  end
33
25
 
26
+ def self.execute_extensions
27
+ @execute_extensions ||= []
28
+ end
29
+
34
30
  def self.protected_exceptions
35
31
  @protected_exceptions ||= [Pork::Error, StandardError]
36
32
  end
@@ -87,13 +83,13 @@ module Pork
87
83
  def self.execute
88
84
  if ENV['PORK_TEST']
89
85
  if tests = Executor[ENV['PORK_TEST']]
90
- @stat = Executor.execute(execute_mode, stat, tests)
86
+ @stat = Executor.execute(:paths => tests)
91
87
  else
92
88
  puts "Cannot find test: #{ENV['PORK_TEST']}"
93
89
  exit 254
94
90
  end
95
91
  else
96
- @stat = Executor.execute(execute_mode, stat)
92
+ @stat = Executor.execute
97
93
  end
98
94
  end
99
95
 
@@ -102,7 +98,7 @@ module Pork
102
98
  execute_mode(ENV['PORK_MODE'])
103
99
  report_mode(ENV['PORK_REPORT'])
104
100
  trap
105
- stat.loaded(@at, @files)
101
+ stat.loaded(@at, @files) if instance_variable_defined?(:@at)
106
102
  execute
107
103
  stat.report
108
104
  end
@@ -0,0 +1,31 @@
1
+
2
+ require 'pork/suite'
3
+
4
+ module Pork
5
+ module API
6
+ module_function
7
+ def before &block
8
+ Suite.before(&block)
9
+ end
10
+
11
+ def after &block
12
+ Suite.after(&block)
13
+ end
14
+
15
+ def copy desc=:default, &block
16
+ Suite.copy(desc, &block)
17
+ end
18
+
19
+ def paste desc=:default, *args
20
+ Suite.paste(desc, *args)
21
+ end
22
+
23
+ def describe desc=:default, opts={}, &suite
24
+ Suite.describe(desc, opts, &suite)
25
+ end
26
+
27
+ def would desc=:default, opts={}, &test
28
+ Suite.would(desc, opts, &test)
29
+ end
30
+ end
31
+ end
@@ -11,8 +11,8 @@ module Pork
11
11
  end
12
12
 
13
13
  def run_after context
14
+ after.reverse_each{ |b| context.instance_eval(&b) }
14
15
  super_env && super_env.run_after(context)
15
- after.each{ |b| context.instance_eval(&b) }
16
16
  end
17
17
  end
18
18
  end
@@ -1,16 +1,30 @@
1
1
 
2
- require 'pork/imp'
3
- require 'pork/isolate'
4
- require 'pork/context'
2
+ require 'pork/suite'
3
+ require 'pork/isolator'
5
4
 
6
5
  module Pork
7
- class Executor < Struct.new(:pork_stat, :pork_description)
8
- # we don't want this method from Struct.new, it's confusing when
9
- # pork/isolate was not loaded. (i.e. isolate would override it anyway)
10
- singleton_class.superclass.send(:remove_method, :[])
6
+ class Executor < Struct.new(:isolator)
7
+ def self.[] index
8
+ Isolator[][index]
9
+ end
11
10
 
12
- extend Isolate, Imp
13
- include Context
14
- init
11
+ def self.execute mode: Pork.execute_mode,
12
+ stat: Pork.stat,
13
+ suite: Suite,
14
+ isolator: Isolator[suite],
15
+ paths: isolator.all_paths
16
+ require "pork/mode/#{mode}"
17
+ Pork.const_get(mode.capitalize).new(isolator).execute(stat, paths)
18
+ end
19
+
20
+ def initialize new_isolator
21
+ super(new_isolator)
22
+ extensions = Pork.execute_extensions
23
+ extend(*extensions.reverse) if extensions.any?
24
+ end
25
+
26
+ def execute stat=Stat.new, paths=isolator.all_paths
27
+ raise NotImplementedError
28
+ end
15
29
  end
16
30
  end
@@ -1,6 +1,14 @@
1
1
 
2
+ require 'pork/env'
3
+ require 'pork/suite'
4
+
2
5
  module Pork
3
- module Isolate
6
+ class Isolator < Struct.new(:suite)
7
+ def self.[] suite=Suite
8
+ @map ||= {}
9
+ @map[suite] ||= new(suite)
10
+ end
11
+
4
12
  def all_tests
5
13
  @all_tests ||= build_all_tests
6
14
  end
@@ -39,7 +47,7 @@ module Pork
39
47
  env = Env.new(super_env)
40
48
  idx = path.first
41
49
 
42
- @tests.first(idx).each do |(type, arg, _)|
50
+ suite.tests.first(idx).each do |(type, arg, _)|
43
51
  case type
44
52
  when :before
45
53
  env.before << arg
@@ -49,24 +57,23 @@ module Pork
49
57
  end
50
58
 
51
59
  if path.size == 1
52
- _, desc, test = @tests[idx]
53
- run(stat, desc, test, env)
60
+ _, desc, test = suite.tests[idx]
61
+ suite.run(stat, desc, test, env)
54
62
  else
55
- @tests[idx][1].isolate(stat, path.drop(1), env)
63
+ Isolator[suite.tests[idx][1]].isolate(stat, path.drop(1), env)
56
64
  end
57
65
 
58
66
  stat
59
67
  end
60
68
 
61
69
  def build_all_tests result={}, path=[]
62
- @tests.each_with_index.inject(result) do |r,
63
- ((type, imp, test, opts),
64
- index)|
70
+ suite.tests.each_with_index.inject(result) do |
71
+ r, ((type, imp, test, opts), index)|
65
72
  current = path + [index]
66
73
 
67
74
  case type
68
75
  when :describe
69
- imp.build_all_tests(r, current) do |nested|
76
+ Isolator[imp].build_all_tests(r, current) do |nested|
70
77
  store_path(r, nested, test, opts[:groups])
71
78
  end
72
79
  when :would
@@ -2,22 +2,21 @@
2
2
  require 'pork/mode/shuffled'
3
3
 
4
4
  module Pork
5
- module Parallel
5
+ class Parallel < Struct.new(:isolator)
6
6
  def cores
7
7
  8
8
8
  end
9
9
 
10
- def parallel stat=Stat.new, paths=all_paths
10
+ def execute stat=Stat.new, paths=isolator.all_paths
11
+ executor = Shuffled.new(isolator)
11
12
  stat.prepare(paths)
12
13
  paths.shuffle.each_slice(cores).map do |paths_slice|
13
14
  Thread.new do
14
- execute(:shuffled,
15
- Stat.new(stat.reporter, stat.protected_exceptions),
16
- paths_slice)
15
+ executor.execute(
16
+ Stat.new(stat.reporter, stat.protected_exceptions),
17
+ paths_slice)
17
18
  end
18
19
  end.map(&:value).inject(stat, &:merge)
19
20
  end
20
21
  end
21
-
22
- Executor.extend(Parallel)
23
22
  end
@@ -1,11 +1,11 @@
1
1
 
2
+ require 'pork/executor'
3
+
2
4
  module Pork
3
- module Sequential
4
- def sequential stat=Stat.new, paths=all_paths
5
+ class Sequential < Executor
6
+ def execute stat=Stat.new, paths=isolator.all_paths
5
7
  stat.prepare(paths)
6
- paths.inject(stat, &method(:isolate))
8
+ paths.inject(stat, &isolator.method(:isolate))
7
9
  end
8
10
  end
9
-
10
- Executor.extend(Sequential)
11
11
  end
@@ -1,11 +1,11 @@
1
1
 
2
+ require 'pork/executor'
3
+
2
4
  module Pork
3
- module Shuffled
4
- def shuffled stat=Stat.new, paths=all_paths
5
+ class Shuffled < Executor
6
+ def execute stat=Stat.new, paths=isolator.all_paths
5
7
  stat.prepare(paths)
6
- paths.shuffle.inject(stat, &method(:isolate))
8
+ paths.shuffle.inject(stat, &isolator.method(:isolate))
7
9
  end
8
10
  end
9
-
10
- Executor.extend(Shuffled)
11
11
  end
@@ -1,6 +1,4 @@
1
1
 
2
- require 'pork'
3
-
4
2
  module Pork
5
3
  module BottomupBacktrace
6
4
  private
@@ -1,6 +1,4 @@
1
1
 
2
- require 'pork'
3
-
4
2
  module Pork
5
3
  module Color
6
4
  def msg_skip ; yellow(super); end
@@ -1,6 +1,4 @@
1
1
 
2
- require 'pork/executor'
3
-
4
2
  module Kernel
5
3
  def should *args, &block
6
4
  stat = Thread.current.group.list.find{ |t| t[:pork_stat] }[:pork_stat]
@@ -10,18 +8,18 @@ end
10
8
 
11
9
  module Pork
12
10
  module Should
13
- def execute mode, stat=Stat.new, *args
11
+ def execute stat=Stat.new, *args
14
12
  thread = Thread.current
15
13
  original_group, group = thread.group, ThreadGroup.new
16
14
  original_stat = thread[:pork_stat]
17
15
  group.add(thread)
18
16
  thread[:pork_stat] = stat
19
- super(mode, stat, *args)
17
+ super(stat, *args)
20
18
  ensure
21
19
  thread[:pork_stat] = original_stat
22
20
  original_group.add(thread)
23
21
  end
24
22
  end
25
23
 
26
- Executor.extend(Should)
24
+ execute_extensions << Should
27
25
  end
@@ -5,7 +5,8 @@ module Pork
5
5
  module Report::Imp
6
6
  def initialize o=$stdout
7
7
  super
8
- extend(*Pork.report_extensions.reverse) if Pork.report_extensions.any?
8
+ extensions = Pork.report_extensions
9
+ extend(*extensions.reverse) if extensions.any?
9
10
  end
10
11
 
11
12
  def case_start _; end
@@ -152,5 +153,5 @@ module Pork
152
153
  end
153
154
  end
154
155
 
155
- Report.__send__(:include, Report::Imp)
156
+ Report.include(Report::Imp)
156
157
  end
@@ -3,7 +3,7 @@ require 'pork/report/dot'
3
3
 
4
4
  module Pork
5
5
  class Description < Dot
6
- attr_accessor :last_executor
6
+ attr_accessor :last_suite
7
7
 
8
8
  def msg_pass
9
9
  msg = "\ro"
@@ -19,17 +19,17 @@ module Pork
19
19
  def msg_errored; "\r#{super}"; end
20
20
 
21
21
  def case_start context
22
- self.last_executor ||= Executor
23
- executor = context.class
24
- levels = executor.ancestors.drop(1).count{ |a| a <= Executor }
22
+ self.last_suite ||= Suite
23
+ suite = context.class
24
+ levels = suite.ancestors.drop(1).count{ |a| a <= Suite }
25
25
 
26
- if executor != Executor && last_executor != executor
27
- io.puts "#{' ' * (levels - 1)}#{executor.desc}"
26
+ if suite != Suite && last_suite != suite
27
+ io.puts "#{' ' * (levels - 1)}#{suite.desc}"
28
28
  end
29
29
 
30
30
  io.print "#{' ' * levels}#{context.pork_description}"
31
31
 
32
- self.last_executor = executor
32
+ self.last_suite = suite
33
33
  end
34
34
 
35
35
  def case_end
@@ -75,12 +75,11 @@ module Pork
75
75
  end
76
76
  end
77
77
 
78
- def case_pass ; end
79
78
  def case_skip ; end
80
79
  def case_failed ; self.failed = true; end
81
80
  def case_errored; self.failed = true; end
82
81
 
83
- def case_end
82
+ def case_pass
84
83
  bar.tick
85
84
  end
86
85
 
@@ -0,0 +1,54 @@
1
+
2
+ require 'pork/error'
3
+
4
+ module Pork
5
+ class Runner < Struct.new(:suite, :seed, :stat, :desc, :test, :env)
6
+ def run
7
+ assertions = stat.assertions
8
+ context = suite.new(stat, desc)
9
+
10
+ stat.reporter.case_start(context)
11
+
12
+ passed = protected do
13
+ env.run_before(context)
14
+ context.instance_eval(&test)
15
+ end
16
+
17
+ protected{ env.run_after(context) }
18
+
19
+ if passed
20
+ if assertions == stat.assertions
21
+ protected{ raise Error.new('Missing assertions') }
22
+ else
23
+ stat.reporter.case_pass
24
+ end
25
+ end
26
+
27
+ stat.incr_tests
28
+ stat.reporter.case_end
29
+ end
30
+
31
+ private
32
+ def protected
33
+ yield
34
+ true
35
+ rescue *stat.protected_exceptions => e
36
+ case e
37
+ when Skip
38
+ stat.incr_skips
39
+ stat.reporter.case_skip
40
+ else
41
+ err = [e, suite.description_for("would #{desc}"), test, seed]
42
+ case e
43
+ when Failure
44
+ stat.add_failure(err)
45
+ stat.reporter.case_failed
46
+ else
47
+ stat.add_error(err)
48
+ stat.reporter.case_errored
49
+ end
50
+ end
51
+ false
52
+ end
53
+ end
54
+ end
@@ -63,5 +63,5 @@ module Pork
63
63
  end
64
64
  end
65
65
 
66
- Stat.__send__(:include, Stat::Imp)
66
+ Stat.include(Stat::Imp)
67
67
  end
@@ -0,0 +1,59 @@
1
+
2
+ require 'pork/runner'
3
+ require 'pork/context'
4
+
5
+ module Pork
6
+ class Suite < Struct.new(:pork_stat, :pork_description)
7
+ module Imp
8
+ attr_reader :desc, :tests
9
+
10
+ def before &block; @tests << [:before, block]; end
11
+ def after &block; @tests << [:after , block]; end
12
+
13
+ def copy desc=:default, &suite
14
+ @stash[desc] = suite
15
+ end
16
+ def paste desc=:default, *args
17
+ module_exec(*args, &search_stash(desc))
18
+ end
19
+
20
+ def describe desc=:default, opts={}, &suite
21
+ executor = Class.new(self){ init(desc) }
22
+ executor.module_eval(&suite)
23
+ @tests << [:describe, executor, suite, opts]
24
+ end
25
+
26
+ def would desc=:default, opts={}, &test
27
+ raise ArgumentError.new("no block given") unless test
28
+ @tests << [:would , desc , test, opts]
29
+ end
30
+
31
+ def description_for name=''
32
+ if @super_executor
33
+ "#{@super_executor.description_for}#{@desc}: #{name}"
34
+ else
35
+ name
36
+ end
37
+ end
38
+
39
+ def run *args
40
+ Runner.new(self, Pork.reseed, *args).run
41
+ end
42
+
43
+ private
44
+ def init desc=''
45
+ @desc, @tests, @stash = desc, [], {}
46
+ @super_executor = ancestors[1..-1].find{ |a| a <= Suite }
47
+ end
48
+
49
+ protected
50
+ def search_stash desc
51
+ @stash[desc] or @super_executor && @super_executor.search_stash(desc)
52
+ end
53
+ end
54
+
55
+ extend Imp
56
+ include Context
57
+ init
58
+ end
59
+ end
@@ -1,4 +1,4 @@
1
1
 
2
2
  module Pork
3
- VERSION = '1.5.0'
3
+ VERSION = '2.0.0'
4
4
  end
@@ -1,14 +1,14 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: pork 1.5.0 ruby lib
2
+ # stub: pork 2.0.0 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "pork".freeze
6
- s.version = "1.5.0"
6
+ s.version = "2.0.0"
7
7
 
8
8
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
9
9
  s.require_paths = ["lib".freeze]
10
10
  s.authors = ["Lin Jen-Shin (godfat)".freeze]
11
- s.date = "2016-03-10"
11
+ s.date = "2016-09-10"
12
12
  s.description = "Pork -- Simple and clean and modular testing library.\n\nInspired by [Bacon][].\n\n[Bacon]: https://github.com/chneukirchen/bacon".freeze
13
13
  s.email = ["godfat (XD) godfat.org".freeze]
14
14
  s.files = [
@@ -22,6 +22,7 @@ Gem::Specification.new do |s|
22
22
  "Rakefile".freeze,
23
23
  "TODO.md".freeze,
24
24
  "lib/pork.rb".freeze,
25
+ "lib/pork/api.rb".freeze,
25
26
  "lib/pork/auto.rb".freeze,
26
27
  "lib/pork/context.rb".freeze,
27
28
  "lib/pork/env.rb".freeze,
@@ -30,9 +31,8 @@ Gem::Specification.new do |s|
30
31
  "lib/pork/expect.rb".freeze,
31
32
  "lib/pork/extra/rainbows.rb".freeze,
32
33
  "lib/pork/extra/show_source.rb".freeze,
33
- "lib/pork/imp.rb".freeze,
34
34
  "lib/pork/inspect.rb".freeze,
35
- "lib/pork/isolate.rb".freeze,
35
+ "lib/pork/isolator.rb".freeze,
36
36
  "lib/pork/mode/parallel.rb".freeze,
37
37
  "lib/pork/mode/sequential.rb".freeze,
38
38
  "lib/pork/mode/shuffled.rb".freeze,
@@ -44,7 +44,9 @@ Gem::Specification.new do |s|
44
44
  "lib/pork/report/description.rb".freeze,
45
45
  "lib/pork/report/dot.rb".freeze,
46
46
  "lib/pork/report/progressbar.rb".freeze,
47
+ "lib/pork/runner.rb".freeze,
47
48
  "lib/pork/stat.rb".freeze,
49
+ "lib/pork/suite.rb".freeze,
48
50
  "lib/pork/test.rb".freeze,
49
51
  "lib/pork/version.rb".freeze,
50
52
  "pork.gemspec".freeze,
@@ -53,6 +55,7 @@ Gem::Specification.new do |s|
53
55
  "test/test_bacon.rb".freeze,
54
56
  "test/test_expect.rb".freeze,
55
57
  "test/test_inspect.rb".freeze,
58
+ "test/test_meta.rb".freeze,
56
59
  "test/test_nested.rb".freeze,
57
60
  "test/test_pork_test.rb".freeze,
58
61
  "test/test_readme.rb".freeze,
@@ -60,12 +63,13 @@ Gem::Specification.new do |s|
60
63
  "test/test_stat.rb".freeze]
61
64
  s.homepage = "https://github.com/godfat/pork".freeze
62
65
  s.licenses = ["Apache License 2.0".freeze]
63
- s.rubygems_version = "2.6.1".freeze
66
+ s.rubygems_version = "2.6.6".freeze
64
67
  s.summary = "Pork -- Simple and clean and modular testing library.".freeze
65
68
  s.test_files = [
66
69
  "test/test_bacon.rb".freeze,
67
70
  "test/test_expect.rb".freeze,
68
71
  "test/test_inspect.rb".freeze,
72
+ "test/test_meta.rb".freeze,
69
73
  "test/test_nested.rb".freeze,
70
74
  "test/test_pork_test.rb".freeze,
71
75
  "test/test_readme.rb".freeze,
@@ -236,13 +236,14 @@ describe "before/after" do
236
236
  @a = 2
237
237
  end
238
238
 
239
+ # after should run in reverse order
239
240
  after do
240
- @a.should.eq 2
241
- @a = 3
241
+ @a.should.eq 3
242
242
  end
243
243
 
244
244
  after do
245
- @a.should.eq 3
245
+ @a.should.eq 2
246
+ @a = 3
246
247
  end
247
248
 
248
249
  would "run in the right order" do
@@ -343,7 +344,7 @@ end
343
344
 
344
345
  describe 'describe arguments' do
345
346
  check = lambda do |ctx, desc, name=nil|
346
- ctx.should.lt Pork::Executor
347
+ ctx.should.lt Pork::Suite
347
348
  ctx.description_for(name).should.eq "#{desc}: #{name}"
348
349
  end
349
350
 
@@ -372,8 +373,8 @@ describe 'describe arguments' do
372
373
  end
373
374
 
374
375
  would 'work with namespaced modules' do
375
- str = 'Pork::Executor'
376
- Pork::API.describe(Pork::Executor) do
376
+ str = 'Pork::Suite'
377
+ Pork::API.describe(Pork::Suite) do
377
378
  check[self, str]
378
379
  would 'd' do check[self.class, str, 'd'] end
379
380
  end
@@ -0,0 +1,40 @@
1
+
2
+ require 'pork/test'
3
+
4
+ describe 'meta' do
5
+ before do
6
+ @stat = Pork::Stat.new(Pork.report_class.new(StringIO.new))
7
+ @suite = Class.new(Pork::Suite){init}
8
+ end
9
+
10
+ def execute
11
+ Pork::Executor.execute(:suite => @suite, :stat => @stat)
12
+ end
13
+
14
+ would 'raise missing assertion' do
15
+ @suite.would{}
16
+ @suite.after{ok} # defined after would so no run for that
17
+ stat = execute
18
+ err, _, _ = stat.exceptions.first
19
+
20
+ expect(err).kind_of?(Pork::Error)
21
+ expect(err.message).eq 'Missing assertions'
22
+ end
23
+
24
+ would 'not raise missing assertion if there is one in after block' do
25
+ @suite.after{ok}
26
+ @suite.would{}
27
+ stat = execute
28
+
29
+ expect(stat.exceptions).empty?
30
+ end
31
+
32
+ would 'run after block even if there is an error in test' do
33
+ called = false
34
+ @suite.after{ called = true }
35
+ @suite.would{ flunk }
36
+ execute
37
+
38
+ expect(called).eq true
39
+ end
40
+ end
@@ -78,3 +78,26 @@ describe Pork::Context do
78
78
  expect(pork_description).eq desc
79
79
  end
80
80
  end
81
+
82
+ describe 'assertion in after block' do
83
+ after do
84
+ ok
85
+ end
86
+
87
+ would do
88
+ end
89
+ end
90
+
91
+ describe 'no before/after after would' do
92
+ would do
93
+ ok
94
+ end
95
+
96
+ before do
97
+ flunk
98
+ end
99
+
100
+ after do
101
+ flunk
102
+ end
103
+ end
@@ -2,21 +2,21 @@
2
2
  require 'pork/test'
3
3
 
4
4
  describe 'PORK_TEST=a' do
5
- def verify line, executor, index
6
- path = executor[index].first
7
- type, desc, block, opts = extract(path, executor)
5
+ def verify line, suite, index
6
+ path = Pork::Isolator[suite][index].first
7
+ type, desc, block, opts = extract(path, suite)
8
8
  expect(type) .eq :would
9
9
  expect(desc) .eq 'find the corresponding test case'
10
10
  expect(block.source_location).eq [__FILE__, line]
11
11
  expect(opts) .eq :groups => [:a, :b]
12
12
  end
13
13
 
14
- def extract path, executor
15
- path.inject(executor.instance_variable_get(:@tests)) do |tests, idx|
14
+ def extract path, suite
15
+ path.inject(suite.tests) do |tests, idx|
16
16
  type, arg, = tests[idx]
17
17
  case type
18
18
  when :describe # we need to go deeper
19
- arg.instance_variable_get(:@tests)
19
+ arg.tests
20
20
  else
21
21
  tests[idx] # should end here
22
22
  end
@@ -25,11 +25,11 @@ describe 'PORK_TEST=a' do
25
25
 
26
26
  would 'find the corresponding test case', :groups => [:a, :b] do
27
27
  line = __LINE__ - 1
28
- [self.class, Pork::Executor].each do |executor|
29
- verify(line, executor, "#{__FILE__}:#{__LINE__}") # line
30
- verify(line, executor, 'a') # group
31
- verify(line, executor, "#{__FILE__}:#{__LINE__}") # diff line
32
- verify(line, executor, __FILE__) # file
28
+ [self.class, Pork::Suite].each do |suite|
29
+ verify(line, suite, "#{__FILE__}:#{__LINE__}") # line
30
+ verify(line, suite, 'a') # group
31
+ verify(line, suite, "#{__FILE__}:#{__LINE__}") # diff line
32
+ verify(line, suite, __FILE__) # file
33
33
  # for self.class, would is the 1st, for Pork::Executor, would is 2nd
34
34
  end
35
35
  end
@@ -37,16 +37,18 @@ describe 'PORK_TEST=a' do
37
37
  describe 'PORK_TEST=b' do
38
38
  would 'find both', :groups => [:b] do
39
39
  line = __LINE__ - 1
40
- woulds = Pork::Executor[__FILE__]
41
- woulds .size.should.eq 4
42
- Pork::Executor['a'] .size.should.eq 1
43
- Pork::Executor['b'] .size.should.eq 2
44
- Pork::Executor['b'] .should.eq woulds.first(2)
45
- Pork::Executor['a,b'] .should.eq woulds.first(2)
46
- self.class['a'] .should.nil?
47
- self.class['b'] .size.should.eq 1
40
+ top = Pork::Isolator[]
41
+ woulds = top[__FILE__]
42
+ woulds .size.should.eq 4
43
+ top['a'] .size.should.eq 1
44
+ top['b'] .size.should.eq 2
45
+ top['b'] .should.eq woulds.first(2)
46
+ top['a,b'] .should.eq woulds.first(2)
47
+ local = Pork::Isolator[self.class]
48
+ local['a'] .should.nil?
49
+ local['b'].size.should.eq 1
48
50
 
49
- a, b = Pork::Executor['b'].map{ |path| extract(path, Pork::Executor) }
51
+ a, b = top['b'].map{ |path| extract(path, Pork::Suite) }
50
52
  expect(a[0]) .eq :would
51
53
  expect(a[1]) .eq 'find the corresponding test case'
52
54
  expect(a[3]) .eq :groups => [:a, :b]
@@ -60,12 +62,13 @@ describe 'PORK_TEST=a' do
60
62
  describe 'PORK_TEST=c', :groups => [:c] do
61
63
  would 'inherit groups from describe', :groups => [:d] do
62
64
  line = __LINE__ - 2
63
- c = Pork::Executor['c']
64
- d = Pork::Executor['d']
65
- expect(c.size) .eq 2
66
- expect(d.size) .eq 1
67
- expect(c.first) .eq d.first
68
- expect(Pork::Executor["#{__FILE__}:#{line}"]).eq c
65
+ isolator = Pork::Isolator[]
66
+ c = isolator['c']
67
+ d = isolator['d']
68
+ expect(c.size) .eq 2
69
+ expect(d.size) .eq 1
70
+ expect(c.first) .eq d.first
71
+ expect(isolator["#{__FILE__}:#{line}"]).eq c
69
72
  end
70
73
 
71
74
  would 'dummy' do
@@ -1,13 +1,17 @@
1
1
 
2
2
  require 'pork/test'
3
- require 'uri'
4
3
 
5
4
  describe 'README.md' do
6
5
  File.read("#{File.dirname(File.expand_path(__FILE__))}/../README.md").
7
6
  scan(%r{``` ruby\nrequire 'pork/auto'\n(.+?)\n```}m).
8
7
  each.with_index do |(code), index|
9
8
  would 'pass from README.md #%02d' % index do
10
- Module.new{ extend Pork::API; instance_eval(code) }
9
+ suite = Class.new(Pork::Suite) do
10
+ init
11
+ instance_eval(code)
12
+ end
13
+
14
+ Pork::Executor.execute(:suite => suite)
11
15
  ok
12
16
  end
13
17
  end
@@ -4,7 +4,7 @@ require 'stringio'
4
4
 
5
5
  describe Pork::Stat do
6
6
  before do
7
- @executor = Class.new(Pork::Executor){init}
7
+ @suite = Class.new(Pork::Suite){init}
8
8
  end
9
9
 
10
10
  def skip_if_backtrace_is_wrong
@@ -23,7 +23,7 @@ describe Pork::Stat do
23
23
  def run check=:expect_one_error
24
24
  stat = Pork::Stat.new(Pork.report_class.new(StringIO.new))
25
25
  stat.protected_exceptions = pork_stat.protected_exceptions
26
- @stat = @executor.execute(Pork.execute_mode, stat)
26
+ @stat = Pork::Executor.execute(:suite => @suite, :stat => stat)
27
27
  send(check)
28
28
  end
29
29
 
@@ -42,17 +42,19 @@ describe Pork::Stat do
42
42
  end
43
43
 
44
44
  would 'rescue custom errors' do
45
- @executor.would{ raise WebMockError }
45
+ @suite.would{ raise WebMockError }
46
46
  run
47
47
  end
48
48
 
49
49
  would 'always have backtrace' do
50
- @executor.would
50
+ @suite.would{}
51
51
  run
52
52
 
53
53
  err, _, test = @stat.exceptions.first
54
54
  err.set_backtrace([])
55
55
 
56
+ expect(err).kind_of?(Pork::Error)
57
+ expect(err.message).eq 'Missing assertions'
56
58
  expect(@stat.reporter.send(:show_backtrace, test, err)).not.empty?
57
59
  end
58
60
 
@@ -65,28 +67,28 @@ describe Pork::Stat do
65
67
  end
66
68
 
67
69
  would 'one line' do
68
- @executor.would{ flunk }
69
- verify('=> @executor.would{ flunk }')
70
+ @suite.would{ flunk }
71
+ verify('=> @suite.would{ flunk }')
70
72
  end
71
73
 
72
74
  would 'more lines' do
73
- @executor.would do
75
+ @suite.would do
74
76
  flunk
75
77
  end
76
78
  verify(<<-SOURCE.chomp)
77
- @executor.would do
79
+ @suite.would do
78
80
  \e[41m => flunk\e[0m
79
81
  end
80
82
  SOURCE
81
83
  end
82
84
 
83
85
  would 'multiple lines' do
84
- @executor.would do
86
+ @suite.would do
85
87
  raise \
86
88
  'error'
87
89
  end
88
90
  verify(<<-SOURCE.chomp)
89
- @executor.would do
91
+ @suite.would do
90
92
  \e[41m => raise \\\e[0m
91
93
  \e[41m => 'error'\e[0m
92
94
  end
@@ -95,14 +97,14 @@ describe Pork::Stat do
95
97
 
96
98
  would 'multiple lines with == {}' do
97
99
  skip_if_backtrace_is_wrong
98
- @executor.would do
100
+ @suite.would do
99
101
  0.should == {
100
102
 
101
103
 
102
104
  }
103
105
  end
104
106
  verify(<<-SOURCE.chomp, :expect_one_failure)
105
- @executor.would do
107
+ @suite.would do
106
108
  \e[41m => 0.should == {\e[0m
107
109
  \e[41m => \e[0m
108
110
  \e[41m => \e[0m
@@ -112,20 +114,20 @@ describe Pork::Stat do
112
114
  end
113
115
 
114
116
  would 'show the line in the test, not other methods' do
115
- @executor.send(:define_method, :f){ flunk }
116
- @executor.would do
117
+ @suite.send(:define_method, :f){ flunk }
118
+ @suite.would do
117
119
  f
118
120
  end
119
121
  verify(<<-SOURCE.chomp)
120
- @executor.would do
122
+ @suite.would do
121
123
  \e[41m => f\e[0m
122
124
  end
123
125
  SOURCE
124
126
  end
125
127
 
126
128
  would 'show the line in the test, even if it is from 3rd party' do
127
- @executor.would{ flunk }
128
- verify("=> @executor.would{ flunk }") do |err|
129
+ @suite.would{ flunk }
130
+ verify("=> @suite.would{ flunk }") do |err|
129
131
  err.set_backtrace(err.backtrace.unshift("bad.rb:#{__LINE__}"))
130
132
  end
131
133
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pork
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lin Jen-Shin (godfat)
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-10 00:00:00.000000000 Z
11
+ date: 2016-09-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: method_source
@@ -60,6 +60,7 @@ files:
60
60
  - Rakefile
61
61
  - TODO.md
62
62
  - lib/pork.rb
63
+ - lib/pork/api.rb
63
64
  - lib/pork/auto.rb
64
65
  - lib/pork/context.rb
65
66
  - lib/pork/env.rb
@@ -68,9 +69,8 @@ files:
68
69
  - lib/pork/expect.rb
69
70
  - lib/pork/extra/rainbows.rb
70
71
  - lib/pork/extra/show_source.rb
71
- - lib/pork/imp.rb
72
72
  - lib/pork/inspect.rb
73
- - lib/pork/isolate.rb
73
+ - lib/pork/isolator.rb
74
74
  - lib/pork/mode/parallel.rb
75
75
  - lib/pork/mode/sequential.rb
76
76
  - lib/pork/mode/shuffled.rb
@@ -82,7 +82,9 @@ files:
82
82
  - lib/pork/report/description.rb
83
83
  - lib/pork/report/dot.rb
84
84
  - lib/pork/report/progressbar.rb
85
+ - lib/pork/runner.rb
85
86
  - lib/pork/stat.rb
87
+ - lib/pork/suite.rb
86
88
  - lib/pork/test.rb
87
89
  - lib/pork/version.rb
88
90
  - pork.gemspec
@@ -91,6 +93,7 @@ files:
91
93
  - test/test_bacon.rb
92
94
  - test/test_expect.rb
93
95
  - test/test_inspect.rb
96
+ - test/test_meta.rb
94
97
  - test/test_nested.rb
95
98
  - test/test_pork_test.rb
96
99
  - test/test_readme.rb
@@ -116,7 +119,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
116
119
  version: '0'
117
120
  requirements: []
118
121
  rubyforge_project:
119
- rubygems_version: 2.6.1
122
+ rubygems_version: 2.6.6
120
123
  signing_key:
121
124
  specification_version: 4
122
125
  summary: Pork -- Simple and clean and modular testing library.
@@ -124,6 +127,7 @@ test_files:
124
127
  - test/test_bacon.rb
125
128
  - test/test_expect.rb
126
129
  - test/test_inspect.rb
130
+ - test/test_meta.rb
127
131
  - test/test_nested.rb
128
132
  - test/test_pork_test.rb
129
133
  - test/test_readme.rb
@@ -1,88 +0,0 @@
1
-
2
- require 'pork/env'
3
- require 'pork/stat'
4
- require 'pork/error'
5
- require 'pork/expect'
6
-
7
- module Pork
8
- module Imp
9
- attr_reader :desc, :tests
10
-
11
- def before &block; @tests << [:before, block]; end
12
- def after &block; @tests << [:after , block]; end
13
-
14
- def copy desc=:default, &suite
15
- @stash[desc] = suite
16
- end
17
- def paste desc=:default, *args
18
- module_exec(*args, &search_stash(desc))
19
- end
20
-
21
- def describe desc=:default, opts={}, &suite
22
- executor = Class.new(self){ init("#{desc}: ") }
23
- executor.module_eval(&suite)
24
- @tests << [:describe, executor, suite || lambda{}, opts]
25
- end
26
-
27
- def would desc=:default, opts={}, &test
28
- @tests << [:would , desc , test || lambda{}, opts]
29
- end
30
-
31
- def execute mode, *args
32
- require "pork/mode/#{mode}"
33
- public_send(mode, *args)
34
- end
35
-
36
- private
37
- def init desc=''
38
- @desc, @tests, @stash = desc, [], {}
39
- @super_executor = ancestors[1..-1].find{ |a| a <= Executor }
40
- end
41
-
42
- def run stat, desc, test, env
43
- assertions = stat.assertions
44
- context = new(stat, desc)
45
- seed = Pork.reseed
46
- stat.reporter.case_start(context)
47
- run_protected(stat, desc, test, seed) do
48
- env.run_before(context)
49
- context.instance_eval(&test)
50
- raise Error.new('Missing assertions') if assertions == stat.assertions
51
- stat.reporter.case_pass
52
- end
53
- ensure
54
- stat.incr_tests
55
- run_protected(stat, desc, test, seed){ env.run_after(context) }
56
- stat.reporter.case_end
57
- end
58
-
59
- def run_protected stat, desc, test, seed
60
- yield
61
- rescue *stat.protected_exceptions => e
62
- case e
63
- when Skip
64
- stat.incr_skips
65
- stat.reporter.case_skip
66
- else
67
- err = [e, description_for("would #{desc}"), test, seed]
68
- case e
69
- when Failure
70
- stat.add_failure(err)
71
- stat.reporter.case_failed
72
- else
73
- stat.add_error(err)
74
- stat.reporter.case_errored
75
- end
76
- end
77
- end
78
-
79
- protected
80
- def search_stash desc
81
- @stash[desc] or @super_executor && @super_executor.search_stash(desc)
82
- end
83
-
84
- def description_for name=''
85
- "#{@super_executor && @super_executor.description_for}#{@desc}#{name}"
86
- end
87
- end
88
- end