pork 1.5.0 → 2.1.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.
- checksums.yaml +5 -5
- data/.gitlab-ci.yml +40 -0
- data/.gitmodules +1 -1
- data/CHANGES.md +41 -0
- data/Gemfile +0 -4
- data/README.md +63 -18
- data/Rakefile +5 -4
- data/TODO.md +0 -2
- data/lib/pork/api.rb +35 -0
- data/lib/pork/env.rb +1 -1
- data/lib/pork/executor.rb +24 -10
- data/lib/pork/extra/show_source.rb +21 -2
- data/lib/pork/isolator.rb +145 -0
- data/lib/pork/mode/parallel.rb +6 -7
- data/lib/pork/mode/sequential.rb +5 -5
- data/lib/pork/mode/shuffled.rb +5 -5
- data/lib/pork/more/bottomup_backtrace.rb +0 -2
- data/lib/pork/more/color.rb +0 -2
- data/lib/pork/more/should.rb +9 -9
- data/lib/pork/report/description.rb +7 -7
- data/lib/pork/report/progressbar.rb +1 -2
- data/lib/pork/report.rb +17 -13
- data/lib/pork/runner.rb +54 -0
- data/lib/pork/stat.rb +1 -1
- data/lib/pork/suite.rb +74 -0
- data/lib/pork/version.rb +1 -1
- data/lib/pork.rb +10 -18
- data/pork.gemspec +23 -23
- data/task/README.md +8 -8
- data/task/gemgem.rb +32 -8
- data/test/test_around.rb +64 -0
- data/test/test_bacon.rb +7 -6
- data/test/test_isolator.rb +29 -0
- data/test/test_meta.rb +40 -0
- data/test/test_nested.rb +24 -1
- data/test/test_pork_test.rb +29 -26
- data/test/test_readme.rb +6 -2
- data/test/test_stat.rb +19 -17
- data/test/test_suite.rb +10 -0
- metadata +20 -11
- data/.travis.yml +0 -15
- data/lib/pork/imp.rb +0 -88
- data/lib/pork/isolate.rb +0 -98
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 6ef62f89f8c80fddee9ebd8e670cfa8de340a312531d022a3e49510dc7dd218f
|
4
|
+
data.tar.gz: 1f3af07cdc623ec24ba294fc41409f958a7fb8c89961388d98915bc648dfb142
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e8c95acab07773aa0fd2f629c41c7a08d50b747c44649a3981021c5f64d0bc08f58a1b2de3ac78c317c3519c692dff2c6f473f32fcf37d806f367e65bb5fac28
|
7
|
+
data.tar.gz: 7b24bb5ec0792941b51ed0b2f69b90f17465fd68401db9835b42ac17b8719ed3c2936a683c6aa22f6165f9d9b01c94d5f5e90329c55c83868d051f4883004910
|
data/.gitlab-ci.yml
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
|
2
|
+
stages:
|
3
|
+
- test
|
4
|
+
|
5
|
+
.test:
|
6
|
+
stage: test
|
7
|
+
image: ruby:${RUBY_VERSION}-bullseye
|
8
|
+
variables:
|
9
|
+
GIT_DEPTH: "1"
|
10
|
+
GIT_SUBMODULE_STRATEGY: recursive
|
11
|
+
GIT_SUBMODULE_PATHS: task
|
12
|
+
RUBYOPT: --enable-frozen-string-literal
|
13
|
+
before_script:
|
14
|
+
- bundle install --retry=3
|
15
|
+
- unset CI # Coverage doesn't work well with frozen literal
|
16
|
+
script:
|
17
|
+
- ruby -vr bundler/setup -S rake test
|
18
|
+
|
19
|
+
ruby:3.0:
|
20
|
+
extends:
|
21
|
+
- .test
|
22
|
+
variables:
|
23
|
+
RUBY_VERSION: '3.0'
|
24
|
+
|
25
|
+
ruby:3.1:
|
26
|
+
extends:
|
27
|
+
- .test
|
28
|
+
variables:
|
29
|
+
RUBY_VERSION: '3.1'
|
30
|
+
|
31
|
+
ruby:3.2:
|
32
|
+
extends:
|
33
|
+
- .test
|
34
|
+
variables:
|
35
|
+
RUBY_VERSION: '3.2'
|
36
|
+
|
37
|
+
jruby:latest:
|
38
|
+
extends:
|
39
|
+
- .test
|
40
|
+
image: jruby:latest
|
data/.gitmodules
CHANGED
data/CHANGES.md
CHANGED
@@ -1,5 +1,46 @@
|
|
1
1
|
# CHANGES
|
2
2
|
|
3
|
+
## Pork 2.1.0 -- 2022-12-28
|
4
|
+
|
5
|
+
### Bugs fixed
|
6
|
+
|
7
|
+
* `Pork.show_source` can work under frozen literal string mode now.
|
8
|
+
* Fix picking the right test for the file line number from `ENV['PORK_TEST']`
|
9
|
+
(I totally forgot the details for this from 2017, but I think it should
|
10
|
+
make it more accurate anyway)
|
11
|
+
* Ruby 3.2 compatibility fix. (Removed the use of `Random::DEFAULT`)
|
12
|
+
|
13
|
+
### Enhancement
|
14
|
+
|
15
|
+
* Introduced `Pork::API.around` which will pass the test object to the block,
|
16
|
+
and whenever the object is called with `call` it'll run the test. Note that
|
17
|
+
if `call` was never called, it'll act like `Pork::API.before` and the test
|
18
|
+
will still run unlike RSpec. To skip the test, call `skip` directly.
|
19
|
+
|
20
|
+
## Pork 2.0.0 -- 2016-09-10
|
21
|
+
|
22
|
+
### Incompatible changes
|
23
|
+
|
24
|
+
* `Pork::Executor` is now renamed to `Pork::Suite`, and the new
|
25
|
+
`Pork::Executor` would be served as the real executor who's responsible
|
26
|
+
for running the test suites!
|
27
|
+
* `Pork::Executor.execute` would now take a hash as the argument.
|
28
|
+
* `Pork::Suite.after` would now run in a reverse manner because that would
|
29
|
+
serve better as a destructor.
|
30
|
+
|
31
|
+
### Enhancement
|
32
|
+
|
33
|
+
* `Pork::Suite.desc` would now preserve the original argument being passed to
|
34
|
+
`Pork::Suite.describe`, rather than converting it to a string.
|
35
|
+
* Major internal structure cleanup. Now we don't include everything into the
|
36
|
+
context, but use different objects to do different things. For example,
|
37
|
+
now we have `Pork::Isolator` to isolate the context.
|
38
|
+
* Introduced `Pork.execute_extensions` which would be extending to
|
39
|
+
`Pork::Executor`. The only extension for it for now is `Pork::Should`.
|
40
|
+
* Don't crash if `Pork.loaded` was never called.
|
41
|
+
* Now you could also make assertions in `after` block without triggering
|
42
|
+
`Missing assertions` errors.
|
43
|
+
|
3
44
|
## Pork 1.5.0 -- 2016-03-10
|
4
45
|
|
5
46
|
### Enhancement
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Pork [](https://gitlab.com/godfat/pork/-/pipelines)
|
2
2
|
|
3
3
|
by Lin Jen-Shin ([godfat](http://godfat.org))
|
4
4
|
|
@@ -7,6 +7,7 @@ by Lin Jen-Shin ([godfat](http://godfat.org))
|
|
7
7
|
* [github](https://github.com/godfat/pork)
|
8
8
|
* [rubygems](https://rubygems.org/gems/pork)
|
9
9
|
* [rdoc](http://rdoc.info/github/godfat/pork)
|
10
|
+
* [issues](https://github.com/godfat/pork/issues) (feel free to ask for support)
|
10
11
|
|
11
12
|
## DESCRIPTION:
|
12
13
|
|
@@ -93,7 +94,7 @@ end
|
|
93
94
|
|
94
95
|
describe 'C' do
|
95
96
|
# Also, we're not forced to include something in all describe blocks.
|
96
|
-
# If we want, we could do this instead: `Pork::
|
97
|
+
# If we want, we could do this instead: `Pork::Suite.include(Module.new)`
|
97
98
|
# That would be the same as including in `Bacon::Context`
|
98
99
|
would 'not respond_to? in_module nor in_describe' do
|
99
100
|
should.not.respond_to?(:in_module)
|
@@ -147,7 +148,7 @@ end
|
|
147
148
|
|
148
149
|
## REQUIREMENTS:
|
149
150
|
|
150
|
-
* Tested with MRI (official CRuby)
|
151
|
+
* Tested with MRI (official CRuby) and JRuby.
|
151
152
|
* (Optional) [method_source][] if you would like to print the source for the
|
152
153
|
failing tests.
|
153
154
|
* (Optional) [ruby-progressbar][] if you like porgressbar for showing
|
@@ -298,7 +299,7 @@ Pork.autorun
|
|
298
299
|
|
299
300
|
Here it `require 'pork/should'`, and it would load the monkey patches for
|
300
301
|
inserting `Kernel#should` shown in SYNOPSIS. This is actually optional,
|
301
|
-
and could be replaced with `Pork::
|
302
|
+
and could be replaced with `Pork::Suite#expect`. For example, we could
|
302
303
|
also write it this way:
|
303
304
|
|
304
305
|
``` ruby
|
@@ -580,16 +581,16 @@ So this creates a test suite which should be containing various test cases
|
|
580
581
|
suite, which accepts anything could be converted to a string. The _default_
|
581
582
|
description is `:default` (which would be converted to `'default: '`)
|
582
583
|
|
583
|
-
Each `describe` block would create a new subclass of `Pork::
|
584
|
+
Each `describe` block would create a new subclass of `Pork::Suite` for
|
584
585
|
isolating test suites. Each nested `describe` block would be a subclass of
|
585
|
-
its parent `Pork::
|
586
|
+
its parent `Pork::Suite`.
|
586
587
|
|
587
588
|
``` ruby
|
588
589
|
require 'pork/auto'
|
589
590
|
|
590
591
|
describe do
|
591
592
|
would 'be default: for the default description' do
|
592
|
-
self.class.desc.should.eq
|
593
|
+
self.class.desc.should.eq :default
|
593
594
|
end
|
594
595
|
end
|
595
596
|
```
|
@@ -602,7 +603,7 @@ description of the test case, which accepts anything could be converted to
|
|
602
603
|
a string. The _default_ description is also `:default`.
|
603
604
|
|
604
605
|
Each `would` block would be run inside a new instance of the describing
|
605
|
-
`Pork::
|
606
|
+
`Pork::Suite` to isolate instance variables.
|
606
607
|
|
607
608
|
### Pork::API.before
|
608
609
|
|
@@ -637,20 +638,21 @@ end
|
|
637
638
|
Each `after` block would be called after each `would` block (test case).
|
638
639
|
You would probably want to cleanup stuffs inside `after` blocks.
|
639
640
|
|
640
|
-
|
641
|
+
Note that each nested `describe` would also run parents' `after` block in a
|
642
|
+
reverse manner as opposed to `before`.
|
641
643
|
|
642
644
|
``` ruby
|
643
645
|
require 'pork/auto'
|
644
646
|
|
645
647
|
describe do
|
646
648
|
after do
|
647
|
-
@a.should.eq
|
648
|
-
@a += 1
|
649
|
+
@a.should.eq 2
|
649
650
|
end
|
650
651
|
|
651
652
|
describe do
|
652
653
|
after do
|
653
|
-
@a.should.eq
|
654
|
+
@a.should.eq 1
|
655
|
+
@a += 1
|
654
656
|
end
|
655
657
|
|
656
658
|
would do
|
@@ -661,6 +663,49 @@ describe do
|
|
661
663
|
end
|
662
664
|
```
|
663
665
|
|
666
|
+
### Pork::API.around
|
667
|
+
|
668
|
+
Each `around` block would be called before each `would` block (test case),
|
669
|
+
and whenever it's called, it can take an argument representing the `would`
|
670
|
+
block (test case). Whenever `call` is called on the test case, it will run.
|
671
|
+
Essentially it's wrapping around the `would` block.
|
672
|
+
|
673
|
+
Note that each nested `describe` would also run parents' `around` block,
|
674
|
+
following the same order of `before` (in order) and `after` (reverse order).
|
675
|
+
|
676
|
+
``` ruby
|
677
|
+
require 'pork/auto'
|
678
|
+
|
679
|
+
describe do
|
680
|
+
around do |test|
|
681
|
+
@a = 0
|
682
|
+
|
683
|
+
test.call
|
684
|
+
|
685
|
+
@a.should.eq 2
|
686
|
+
end
|
687
|
+
|
688
|
+
describe do
|
689
|
+
around do |test|
|
690
|
+
@a.should.eq 0
|
691
|
+
@a += 1
|
692
|
+
|
693
|
+
test.call
|
694
|
+
|
695
|
+
@a.should.eq 1
|
696
|
+
@a += 1
|
697
|
+
end
|
698
|
+
|
699
|
+
would do
|
700
|
+
@a.should.eq 1
|
701
|
+
end
|
702
|
+
end
|
703
|
+
end
|
704
|
+
```
|
705
|
+
|
706
|
+
Note that if `test.call` was never called, it'll just act like a `before`
|
707
|
+
block. All the tests will still run unlike RSpec.
|
708
|
+
|
664
709
|
### Pork::API.copy and Pork::API.paste
|
665
710
|
|
666
711
|
It could be a bit confusing at first, but just think of `copy` as a way to
|
@@ -694,7 +739,7 @@ describe do
|
|
694
739
|
end
|
695
740
|
```
|
696
741
|
|
697
|
-
### Pork::
|
742
|
+
### Pork::Suite#expect
|
698
743
|
|
699
744
|
It is the core of `Kernel#should`. Think of:
|
700
745
|
|
@@ -720,7 +765,7 @@ is equivalent to:
|
|
720
765
|
expect(object, 'message').eq(1)
|
721
766
|
```
|
722
767
|
|
723
|
-
### Pork::
|
768
|
+
### Pork::Suite#skip
|
724
769
|
|
725
770
|
At times we might want to skip some tests while leave the codes there without
|
726
771
|
removing them or commenting them out. This is where `skip` would be helpful.
|
@@ -735,7 +780,7 @@ describe do
|
|
735
780
|
end
|
736
781
|
```
|
737
782
|
|
738
|
-
### Pork::
|
783
|
+
### Pork::Suite#ok
|
739
784
|
|
740
785
|
Because Pork would complain if a test case does not have any assertions,
|
741
786
|
sometimes we might want to tell Pork that it's ok because we've already
|
@@ -758,7 +803,7 @@ describe do
|
|
758
803
|
end
|
759
804
|
```
|
760
805
|
|
761
|
-
### Pork::
|
806
|
+
### Pork::Suite#flunk
|
762
807
|
|
763
808
|
If we're writing program carefully, there are a few cases where a condition
|
764
809
|
would never meet. We could `raise "IMPOSSIBLE"` or we could simply call
|
@@ -1067,9 +1112,9 @@ Have you seen Rainbows!?
|
|
1067
1112
|
|
1068
1113
|
## LICENSE:
|
1069
1114
|
|
1070
|
-
Apache License 2.0
|
1115
|
+
Apache License 2.0 (Apache-2.0)
|
1071
1116
|
|
1072
|
-
Copyright (c) 2014-
|
1117
|
+
Copyright (c) 2014-2022, Lin Jen-Shin (godfat)
|
1073
1118
|
|
1074
1119
|
Licensed under the Apache License, Version 2.0 (the "License");
|
1075
1120
|
you may not use this file except in compliance with the License.
|
data/Rakefile
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
|
2
2
|
begin
|
3
|
-
require "#{
|
3
|
+
require "#{__dir__}/task/gemgem"
|
4
4
|
rescue LoadError
|
5
|
-
sh 'git submodule update --init'
|
5
|
+
sh 'git submodule update --init --recursive'
|
6
6
|
exec Gem.ruby, '-S', $PROGRAM_NAME, *ARGV
|
7
7
|
end
|
8
8
|
|
9
|
-
Gemgem.init(
|
9
|
+
Gemgem.init(__dir__) do |s|
|
10
10
|
require 'pork/version'
|
11
11
|
s.name = 'pork'
|
12
12
|
s.version = Pork::VERSION
|
13
|
+
s.files.delete('screenshot.png')
|
14
|
+
|
13
15
|
%w[method_source ruby-progressbar].
|
14
16
|
each(&s.method(:add_development_dependency))
|
15
|
-
s.files.delete('screenshot.png')
|
16
17
|
end
|
data/TODO.md
CHANGED
data/lib/pork/api.rb
ADDED
@@ -0,0 +1,35 @@
|
|
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 around &block
|
16
|
+
Suite.around(&block)
|
17
|
+
end
|
18
|
+
|
19
|
+
def copy desc=:default, &block
|
20
|
+
Suite.copy(desc, &block)
|
21
|
+
end
|
22
|
+
|
23
|
+
def paste desc=:default, *args
|
24
|
+
Suite.paste(desc, *args)
|
25
|
+
end
|
26
|
+
|
27
|
+
def describe desc=:default, opts={}, &suite
|
28
|
+
Suite.describe(desc, opts, &suite)
|
29
|
+
end
|
30
|
+
|
31
|
+
def would desc=:default, opts={}, &test
|
32
|
+
Suite.would(desc, opts, &test)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/pork/env.rb
CHANGED
data/lib/pork/executor.rb
CHANGED
@@ -1,16 +1,30 @@
|
|
1
1
|
|
2
|
-
require 'pork/
|
3
|
-
require 'pork/
|
4
|
-
require 'pork/context'
|
2
|
+
require 'pork/suite'
|
3
|
+
require 'pork/isolator'
|
5
4
|
|
6
5
|
module Pork
|
7
|
-
class Executor < Struct.new(:
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
class Executor < Struct.new(:isolator)
|
7
|
+
def self.[] index
|
8
|
+
Isolator[][index]
|
9
|
+
end
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
|
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
|
@@ -3,12 +3,31 @@ require 'method_source'
|
|
3
3
|
|
4
4
|
module Pork
|
5
5
|
module ShowSource
|
6
|
+
module FrozenStringFix
|
7
|
+
def extract_first_expression(lines, consume=0, &block)
|
8
|
+
code = consume.zero? ? [] : lines.slice!(0..(consume - 1))
|
9
|
+
|
10
|
+
lines.each do |v|
|
11
|
+
code << v
|
12
|
+
|
13
|
+
result = block ? block.call(code.join) : code.join
|
14
|
+
|
15
|
+
if complete_expression?(result)
|
16
|
+
return result
|
17
|
+
end
|
18
|
+
end
|
19
|
+
raise SyntaxError, "unexpected $end"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
MethodSource.extend(FrozenStringFix)
|
24
|
+
|
6
25
|
def show_source test, err
|
7
26
|
source = test.source
|
8
27
|
sopath = "#{test.source_location.first}:"
|
9
28
|
lowers = test.source_location.last
|
10
29
|
uppers = lowers + source.size
|
11
|
-
lineno = reject_pork(test, err).find do |backtrace|
|
30
|
+
lineno = reject_pork(test, err.backtrace).find do |backtrace|
|
12
31
|
# find the line from the test source, exclude everything else
|
13
32
|
next unless backtrace.start_with?(sopath)
|
14
33
|
number = backtrace[/(?<=\.rb:)\d+/].to_i
|
@@ -28,7 +47,7 @@ module Pork
|
|
28
47
|
end
|
29
48
|
end.join
|
30
49
|
"\n#{result.chomp}"
|
31
|
-
rescue SyntaxError => e
|
50
|
+
rescue SyntaxError, MethodSource::SourceNotFoundError => e
|
32
51
|
"\nPork bug: Cannot parse the source. Please report: #{e}"
|
33
52
|
end
|
34
53
|
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
|
2
|
+
require 'pork/env'
|
3
|
+
require 'pork/suite'
|
4
|
+
|
5
|
+
module Pork
|
6
|
+
class Isolator < Struct.new(:suite)
|
7
|
+
def self.[] suite=Suite
|
8
|
+
@map ||= {}
|
9
|
+
@map[suite] ||= new(suite)
|
10
|
+
end
|
11
|
+
|
12
|
+
def all_tests
|
13
|
+
@all_tests ||= build_all_tests
|
14
|
+
end
|
15
|
+
|
16
|
+
def all_paths
|
17
|
+
(all_tests[:files] || {}).values.flat_map(&:values).flatten(1).uniq
|
18
|
+
end
|
19
|
+
|
20
|
+
def [] index
|
21
|
+
by_groups(index) || by_source(index)
|
22
|
+
end
|
23
|
+
|
24
|
+
def by_groups groups
|
25
|
+
return unless tests = all_tests[:groups]
|
26
|
+
paths = groups.split(',').flat_map do |g|
|
27
|
+
tests[g.strip] || []
|
28
|
+
end.uniq
|
29
|
+
paths unless paths.empty?
|
30
|
+
end
|
31
|
+
|
32
|
+
def by_source source
|
33
|
+
return unless tests = all_tests[:files]
|
34
|
+
file_str, line_str = source.split(':')
|
35
|
+
file, line = File.expand_path(file_str), line_str.to_i
|
36
|
+
return unless cases = tests[file]
|
37
|
+
if line.zero?
|
38
|
+
cases.values.flatten(1).uniq
|
39
|
+
else
|
40
|
+
_, paths = cases.reverse_each.find{ |(l, _)| l <= line }
|
41
|
+
paths
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
protected
|
46
|
+
def isolate stat, path, super_env=nil
|
47
|
+
env = Env.new(super_env)
|
48
|
+
idx = path.first
|
49
|
+
|
50
|
+
suite.tests.first(idx).each do |(type, arg, _)|
|
51
|
+
case type
|
52
|
+
when :before
|
53
|
+
env.before << arg
|
54
|
+
when :after
|
55
|
+
env.after << arg
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
if path.size == 1
|
60
|
+
_, desc, test = suite.tests[idx]
|
61
|
+
suite.run(stat, desc, test, env)
|
62
|
+
else
|
63
|
+
Isolator[suite.tests[idx][1]].isolate(stat, path.drop(1), env)
|
64
|
+
end
|
65
|
+
|
66
|
+
stat
|
67
|
+
end
|
68
|
+
|
69
|
+
def build_all_tests result={}, path=[]
|
70
|
+
suite.tests.each_with_index.inject(result) do |
|
71
|
+
tests, ((type, imp, block, opts), index)|
|
72
|
+
current = path + [index]
|
73
|
+
|
74
|
+
case type
|
75
|
+
when :describe, :would
|
76
|
+
source_location = expand_source_location(block)
|
77
|
+
init_source_store_path(tests, source_location)
|
78
|
+
end
|
79
|
+
|
80
|
+
case type
|
81
|
+
when :describe
|
82
|
+
Isolator[imp].build_all_tests(tests, current) do |nested|
|
83
|
+
store_path(tests, nested, source_location, opts[:groups])
|
84
|
+
end
|
85
|
+
when :would
|
86
|
+
yield(current) if block_given?
|
87
|
+
store_path(tests, current, source_location, opts[:groups])
|
88
|
+
end
|
89
|
+
|
90
|
+
tests
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def expand_source_location block
|
95
|
+
file, line = block.source_location
|
96
|
+
[File.expand_path(file), line]
|
97
|
+
end
|
98
|
+
|
99
|
+
def init_source_store_path tests, source_location
|
100
|
+
source, line = source_location
|
101
|
+
|
102
|
+
root = tests[:files] ||= {}
|
103
|
+
map = root[source] ||= {}
|
104
|
+
|
105
|
+
# Most of the time, line is always getting larger because we're
|
106
|
+
# scanning from top to bottom, and we really need to make sure
|
107
|
+
# that the map is sorted because whenever we're looking up which
|
108
|
+
# test we want from a particular line, we want to find the closest
|
109
|
+
# block rounding up. See Isolator#by_source
|
110
|
+
# However, it's not always appending from top to bottom, because
|
111
|
+
# we might be adding more tests from Suite#paste, and the original
|
112
|
+
# test could be defined in the same file, on previous lines!
|
113
|
+
# Because of this, we really need to make sure the map is balanced.
|
114
|
+
# If we ever have ordered map in Ruby, we don't have to do this...
|
115
|
+
# See the test for Isolator.all_tests (test/test_isolator.rb)
|
116
|
+
balanced_append(map, line, [])
|
117
|
+
end
|
118
|
+
|
119
|
+
def store_path tests, path, source_location, groups
|
120
|
+
store_for_groups(tests, path, groups) if groups
|
121
|
+
store_for_source(tests, path, source_location)
|
122
|
+
end
|
123
|
+
|
124
|
+
def store_for_groups tests, path, groups
|
125
|
+
map = tests[:groups] ||= {}
|
126
|
+
groups.each do |g|
|
127
|
+
(map[g.to_s] ||= []) << path
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def store_for_source tests, path, source_location
|
132
|
+
source, line = source_location
|
133
|
+
|
134
|
+
tests[:files][source][line] << path
|
135
|
+
end
|
136
|
+
|
137
|
+
def balanced_append map, key, value
|
138
|
+
last_key = map.reverse_each.first.first unless map.empty?
|
139
|
+
|
140
|
+
map[key] ||= []
|
141
|
+
|
142
|
+
map.replace(Hash[map.sort]) if last_key && key < last_key
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
data/lib/pork/mode/parallel.rb
CHANGED
@@ -2,22 +2,21 @@
|
|
2
2
|
require 'pork/mode/shuffled'
|
3
3
|
|
4
4
|
module Pork
|
5
|
-
|
5
|
+
class Parallel < Struct.new(:isolator)
|
6
6
|
def cores
|
7
7
|
8
|
8
8
|
end
|
9
9
|
|
10
|
-
def
|
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(
|
15
|
-
|
16
|
-
|
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
|
data/lib/pork/mode/sequential.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
|
2
|
+
require 'pork/executor'
|
3
|
+
|
2
4
|
module Pork
|
3
|
-
|
4
|
-
def
|
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
|
data/lib/pork/mode/shuffled.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
|
2
|
+
require 'pork/executor'
|
3
|
+
|
2
4
|
module Pork
|
3
|
-
|
4
|
-
def
|
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
|