oktest 1.1.1 → 1.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.
- checksums.yaml +4 -4
- data/README.md +197 -22
- data/Rakefile.rb +5 -2
- data/benchmark/Rakefile.rb +4 -0
- data/lib/oktest.rb +170 -58
- data/oktest.gemspec +3 -3
- data/test/assertion_test.rb +1 -1
- data/test/filter_test.rb +1 -1
- data/test/fixture_test.rb +14 -1
- data/test/generator_test.rb +1 -1
- data/test/helper_test.rb +3 -3
- data/test/initialize.rb +1 -1
- data/test/mainapp_test.rb +59 -43
- data/test/matcher_test.rb +1 -1
- data/test/misc_test.rb +5 -5
- data/test/node_test.rb +27 -4
- data/test/reporter_test.rb +30 -31
- data/test/runner_test.rb +8 -17
- data/test/tc.rb +12 -0
- data/test/util_test.rb +71 -1
- data/test/utilhelper_test.rb +84 -0
- data/test/visitor_test.rb +1 -1
- metadata +4 -3
data/lib/oktest.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
3
|
###
|
4
|
-
### $Release: 1.
|
4
|
+
### $Release: 1.2.0 $
|
5
5
|
### $Copyright: copyright(c) 2011-2021 kuwata-lab.com all rights reserved $
|
6
6
|
### $License: MIT License $
|
7
7
|
###
|
@@ -12,7 +12,7 @@ require 'set'
|
|
12
12
|
module Oktest
|
13
13
|
|
14
14
|
|
15
|
-
VERSION = '$Release: 1.
|
15
|
+
VERSION = '$Release: 1.2.0 $'.split()[1]
|
16
16
|
|
17
17
|
|
18
18
|
class OktestError < StandardError
|
@@ -794,6 +794,21 @@ END
|
|
794
794
|
end
|
795
795
|
|
796
796
|
|
797
|
+
module UtilHelper
|
798
|
+
|
799
|
+
def partial_regexp(pattern, begin_='\A', end_='\z', mark="{== ==}")
|
800
|
+
#; [!9drtn] is available in both topic and spec blocks.
|
801
|
+
return Util.partial_regexp(pattern, begin_, end_, mark)
|
802
|
+
end
|
803
|
+
|
804
|
+
def partial_regexp!(pattern, begin_='\A', end_='\z', mark="{== ==}")
|
805
|
+
#; [!wo4hp] is available in both topic and spec blocks.
|
806
|
+
return Util.partial_regexp!(pattern, begin_, end_, mark)
|
807
|
+
end
|
808
|
+
|
809
|
+
end
|
810
|
+
|
811
|
+
|
797
812
|
class Context
|
798
813
|
## * Context class is separated from ScopeNode, TopicNode, and SpecLeaf.
|
799
814
|
## * `topic()` and `spec()` creates subclass of Context class,
|
@@ -801,6 +816,8 @@ END
|
|
801
816
|
## * `scope()` instanciates those subclasses, and run spec blocks
|
802
817
|
## in that instance objects.
|
803
818
|
|
819
|
+
extend UtilHelper
|
820
|
+
|
804
821
|
class << self
|
805
822
|
attr_accessor :__node
|
806
823
|
end
|
@@ -833,26 +850,29 @@ END
|
|
833
850
|
return to
|
834
851
|
end
|
835
852
|
|
836
|
-
def self.spec(desc, tag: nil, &block)
|
853
|
+
def self.spec(desc, tag: nil, fixture: nil, &block)
|
837
854
|
node = @__node
|
838
855
|
node.is_a?(Node) or raise "internal error: node=#{node.inspect}" # for debug
|
856
|
+
#; [!4vkbl] error when `fixture:` keyword arg is not a Hash object.
|
857
|
+
fixture.nil? || fixture.is_a?(Hash) or
|
858
|
+
raise ArgumentError, "spec(fixture: #{fixture.inspect}): fixture argument should be a Hash object, but got #{fixture.class.name} object."
|
839
859
|
#; [!ala78] provides raising TodoException block if block not given.
|
840
860
|
block ||= proc { raise TodoException, "not implemented yet" }
|
841
861
|
#; [!x48db] keeps called location only when block has parameters.
|
842
862
|
if block.parameters.empty?
|
843
863
|
location = nil
|
844
864
|
else
|
845
|
-
location =
|
865
|
+
location = caller_locations(1, 1).first
|
846
866
|
end
|
847
867
|
#; [!c8c8o] creates new spec object.
|
848
|
-
spec = SpecLeaf.new(node, desc, tag: tag, location: location, &block)
|
868
|
+
spec = SpecLeaf.new(node, desc, tag: tag, fixture: fixture, location: location, &block)
|
849
869
|
return spec
|
850
870
|
end
|
851
871
|
|
852
872
|
def self.fixture(name, &block)
|
853
873
|
#; [!8wfrq] registers fixture factory block.
|
854
874
|
#; [!y3ks3] retrieves block parameter names.
|
855
|
-
location =
|
875
|
+
location = caller_locations(1, 1).first
|
856
876
|
@__node.register_fixture_block(name, location, &block)
|
857
877
|
self
|
858
878
|
end
|
@@ -976,6 +996,7 @@ END
|
|
976
996
|
context = @context_class.new()
|
977
997
|
#; [!9hbxn] context object has 'ok()' method.
|
978
998
|
context.extend SpecHelper
|
999
|
+
context.extend UtilHelper
|
979
1000
|
return context
|
980
1001
|
end
|
981
1002
|
|
@@ -1004,7 +1025,7 @@ END
|
|
1004
1025
|
return @hooks[key]
|
1005
1026
|
end
|
1006
1027
|
|
1007
|
-
def _repr(depth=0, buf=
|
1028
|
+
def _repr(depth=0, buf=String.new)
|
1008
1029
|
#; [!bt5j8] builds debug string.
|
1009
1030
|
if depth < 0
|
1010
1031
|
id_str = "%x" % self.object_id
|
@@ -1079,16 +1100,17 @@ END
|
|
1079
1100
|
|
1080
1101
|
class SpecLeaf < Item
|
1081
1102
|
|
1082
|
-
def initialize(parent, desc, tag: nil, location: nil, &block)
|
1103
|
+
def initialize(parent, desc, tag: nil, fixture: nil, location: nil, &block)
|
1083
1104
|
#@parent = parent # not keep parent node to avoid recursive reference
|
1084
1105
|
@desc = desc
|
1085
1106
|
@tag = tag
|
1107
|
+
@fixture = fixture
|
1086
1108
|
@location = location # necessary when raising fixture not found error
|
1087
1109
|
@block = block
|
1088
1110
|
parent.add_child(self) if parent
|
1089
1111
|
end
|
1090
1112
|
|
1091
|
-
attr_reader :desc, :tag, :location, :block
|
1113
|
+
attr_reader :desc, :tag, :fixture, :location, :block
|
1092
1114
|
|
1093
1115
|
def _prefix
|
1094
1116
|
'-'
|
@@ -1109,7 +1131,7 @@ END
|
|
1109
1131
|
nil
|
1110
1132
|
end
|
1111
1133
|
|
1112
|
-
def _repr(depth=0, buf=
|
1134
|
+
def _repr(depth=0, buf=String.new) #:nodoc:
|
1113
1135
|
#; [!6nsgy] builds debug string.
|
1114
1136
|
buf << " " * depth << "- #{@desc}"
|
1115
1137
|
buf << " (tag: #{@tag.inspect})" if @tag
|
@@ -1138,8 +1160,8 @@ END
|
|
1138
1160
|
|
1139
1161
|
def self.scope(tag: nil, &block)
|
1140
1162
|
#; [!kem4y] detects test script filename.
|
1141
|
-
location =
|
1142
|
-
filename = location
|
1163
|
+
location = caller_locations(1, 1).first
|
1164
|
+
filename = location.path.to_s
|
1143
1165
|
#; [!6ullm] changes test script filename from absolute path to relative path.
|
1144
1166
|
if filename
|
1145
1167
|
pwd = Dir.pwd()
|
@@ -1175,7 +1197,7 @@ END
|
|
1175
1197
|
#; [!bc3l2] records invoked location.
|
1176
1198
|
#; [!mqtdy] not record invoked location when `Config.ok_location == false`.
|
1177
1199
|
if Config.ok_location
|
1178
|
-
location =
|
1200
|
+
location = caller_locations(1, 1).first
|
1179
1201
|
else
|
1180
1202
|
location = nil
|
1181
1203
|
end
|
@@ -1190,7 +1212,7 @@ END
|
|
1190
1212
|
#; [!agmx8] records invoked location.
|
1191
1213
|
#; [!a9508] not record invoked location when `Config.ok_location == false`.
|
1192
1214
|
if Config.ok_location
|
1193
|
-
location =
|
1215
|
+
location = caller_locations(1, 1).first
|
1194
1216
|
else
|
1195
1217
|
location = nil
|
1196
1218
|
end
|
@@ -1216,7 +1238,7 @@ END
|
|
1216
1238
|
#; [!wxcsp] raises error when fixture not found.
|
1217
1239
|
unless tuple
|
1218
1240
|
exc = FixtureNotFoundError.new("`#{name.inspect}`: fixture not found.")
|
1219
|
-
exc.set_backtrace([
|
1241
|
+
exc.set_backtrace([caller_locations(1, 1).first.to_s])
|
1220
1242
|
raise exc
|
1221
1243
|
end
|
1222
1244
|
#; [!m4ava] calls fixture block and returns result of it.
|
@@ -1226,7 +1248,7 @@ END
|
|
1226
1248
|
end
|
1227
1249
|
|
1228
1250
|
def TODO()
|
1229
|
-
location =
|
1251
|
+
location = caller_locations(1, 1).first # ex: "foo_test.rb:123:in ...."
|
1230
1252
|
@__TODO = location
|
1231
1253
|
end
|
1232
1254
|
|
@@ -1547,7 +1569,8 @@ END
|
|
1547
1569
|
begin
|
1548
1570
|
params = Util.required_param_names_of_block(spec.block)
|
1549
1571
|
values = params.nil? || params.empty? ? [] \
|
1550
|
-
: get_fixture_values(params, node, spec, context
|
1572
|
+
: get_fixture_values(params, node, spec, context, spec.location,
|
1573
|
+
spec.fixture ? spec.fixture.dup : {})
|
1551
1574
|
spec.run_block_in_context_object(context, *values)
|
1552
1575
|
rescue NoMemoryError => exc; raise exc
|
1553
1576
|
rescue SignalException => exc; raise exc
|
@@ -1572,7 +1595,7 @@ END
|
|
1572
1595
|
exc = TODO_EXCEPTION.new("#{exc.class} raised because not implemented yet")
|
1573
1596
|
end
|
1574
1597
|
location = context.__TODO
|
1575
|
-
exc.set_backtrace([location])
|
1598
|
+
exc.set_backtrace([location.to_s])
|
1576
1599
|
end
|
1577
1600
|
#; [!dihkr] calls 'at_end' blocks, even when exception raised.
|
1578
1601
|
begin
|
@@ -1586,8 +1609,8 @@ END
|
|
1586
1609
|
|
1587
1610
|
private
|
1588
1611
|
|
1589
|
-
def get_fixture_values(names, node, spec, context)
|
1590
|
-
return THE_FIXTURE_MANAGER.get_fixture_values(names, node, spec, context)
|
1612
|
+
def get_fixture_values(names, node, spec, context, location=nil, resolved=nil)
|
1613
|
+
return THE_FIXTURE_MANAGER.get_fixture_values(names, node, spec, context, location, resolved)
|
1591
1614
|
end
|
1592
1615
|
|
1593
1616
|
def _call_blocks_parent_first(node, name, context)
|
@@ -1643,51 +1666,53 @@ END
|
|
1643
1666
|
|
1644
1667
|
class FixtureManager
|
1645
1668
|
|
1646
|
-
def get_fixture_values(names, node, spec, context, location
|
1669
|
+
def get_fixture_values(names, node, spec, context, location, resolved={}, _resolving=[])
|
1647
1670
|
#; [!w6ffs] resolves 'this_topic' fixture name as target objec of current topic.
|
1648
|
-
|
1671
|
+
resolved[:this_topic] = node.target if !resolved.key?(:this_topic) && node.topic?
|
1649
1672
|
#; [!ja2ew] resolves 'this_spec' fixture name as description of current spec.
|
1650
|
-
|
1673
|
+
resolved[:this_spec] = spec.desc if !resolved.key?(:this_spec)
|
1651
1674
|
#; [!v587k] resolves fixtures.
|
1652
|
-
location ||= spec.location
|
1653
1675
|
return names.collect {|name|
|
1654
1676
|
#; [!np4p9] raises error when loop exists in dependency.
|
1655
1677
|
! _resolving.include?(name) or
|
1656
1678
|
raise _looped_dependency_error(name, _resolving, location)
|
1657
|
-
get_fixture_value(name, node, spec, context, location,
|
1679
|
+
get_fixture_value(name, node, spec, context, location, resolved, _resolving)
|
1658
1680
|
}
|
1659
1681
|
end
|
1660
1682
|
|
1661
|
-
def get_fixture_value(name, node, spec, context, location
|
1662
|
-
return
|
1663
|
-
location ||= spec.location
|
1683
|
+
def get_fixture_value(name, node, spec, context, location, resolved={}, _resolving=[])
|
1684
|
+
return resolved[name] if resolved.key?(name)
|
1664
1685
|
tuple = node.get_fixture_block(name)
|
1665
1686
|
if tuple
|
1666
1687
|
block, param_names, location = tuple
|
1667
1688
|
#; [!2esaf] resolves fixture dependencies.
|
1668
1689
|
if param_names
|
1669
1690
|
_resolving << name
|
1670
|
-
args = get_fixture_values(param_names, node, spec, context, location,
|
1691
|
+
args = get_fixture_values(param_names, node, spec, context, location, resolved, _resolving)
|
1671
1692
|
(popped = _resolving.pop) == name or
|
1672
1693
|
raise "** assertion failed: name=#{name.inspect}, resolvng[-1]=#{popped.inspect}"
|
1673
|
-
#; [!4xghy] calls fixture block with context object as self.
|
1674
|
-
val = context.instance_exec(*args, &block)
|
1675
1694
|
else
|
1676
|
-
|
1695
|
+
args = []
|
1677
1696
|
end
|
1697
|
+
#; [!gyyst] overwrites keyword params by fixture values.
|
1698
|
+
kwnames = Util.keyword_param_names_of_block(block)
|
1699
|
+
kwargs = {}
|
1700
|
+
kwnames.each {|name| kwargs[name] = resolved[name] if resolved.key?(name) }
|
1701
|
+
#; [!4xghy] calls fixture block with context object as self.
|
1702
|
+
val = context.instance_exec(*args, **kwargs, &block)
|
1678
1703
|
#; [!8t3ul] caches fixture value to call fixture block only once per spec.
|
1679
|
-
|
1704
|
+
resolved[name] = val
|
1680
1705
|
return val
|
1681
1706
|
elsif node.parent
|
1682
1707
|
#; [!4chb9] traverses parent topics if fixture not found in current topic.
|
1683
|
-
return get_fixture_value(name, node.parent, spec, context, location,
|
1708
|
+
return get_fixture_value(name, node.parent, spec, context, location, resolved, _resolving)
|
1684
1709
|
elsif ! node.equal?(THE_GLOBAL_SCOPE)
|
1685
1710
|
#; [!wt3qk] suports global scope.
|
1686
|
-
return get_fixture_value(name, THE_GLOBAL_SCOPE, spec, context, location,
|
1711
|
+
return get_fixture_value(name, THE_GLOBAL_SCOPE, spec, context, location, resolved, _resolving)
|
1687
1712
|
else
|
1688
1713
|
#; [!nr79z] raises error when fixture not found.
|
1689
1714
|
exc = FixtureNotFoundError.new("#{name}: fixture not found. (spec: #{spec.desc})")
|
1690
|
-
exc.set_backtrace([location]) if location
|
1715
|
+
exc.set_backtrace([location.to_s]) if location
|
1691
1716
|
raise exc
|
1692
1717
|
end
|
1693
1718
|
end
|
@@ -1702,7 +1727,7 @@ END
|
|
1702
1727
|
loop = s1.empty? ? s2 : "#{s1}->#{s2}"
|
1703
1728
|
#location = $1 if location =~ /(.*:\d+)/
|
1704
1729
|
exc = LoopedDependencyError.new("fixture dependency is looped: #{loop}")
|
1705
|
-
exc.set_backtrace([location])
|
1730
|
+
exc.set_backtrace([location.to_s])
|
1706
1731
|
return exc
|
1707
1732
|
end
|
1708
1733
|
|
@@ -1846,7 +1871,7 @@ END
|
|
1846
1871
|
end
|
1847
1872
|
lines = []
|
1848
1873
|
msg.each_line {|line| lines << line }
|
1849
|
-
puts lines.shift.chomp
|
1874
|
+
puts Color.errmsg(lines.shift.chomp)
|
1850
1875
|
puts lines.join.chomp unless lines.empty?
|
1851
1876
|
puts exc.diff if exc.respond_to?(:diff) && exc.diff # for oktest.rb
|
1852
1877
|
end
|
@@ -1912,9 +1937,9 @@ END
|
|
1912
1937
|
$stdout.flush
|
1913
1938
|
end
|
1914
1939
|
label = Color.status(status, LABELS[status] || '???')
|
1915
|
-
msg = "#{' ' * (depth - 1)}- [#{label}] #{spec.desc}"
|
1940
|
+
msg = ["#{' ' * (depth - 1)}- [#{label}] #{spec.desc}"]
|
1916
1941
|
msg << " " << Color.reason("(reason: #{error.message})") if status == :SKIP
|
1917
|
-
puts msg
|
1942
|
+
puts msg.join()
|
1918
1943
|
end
|
1919
1944
|
|
1920
1945
|
end
|
@@ -2100,6 +2125,13 @@ END
|
|
2100
2125
|
return param_names
|
2101
2126
|
end
|
2102
2127
|
|
2128
|
+
def keyword_param_names_of_block(block)
|
2129
|
+
#; [!p6qqp] returns keyword param names of proc object.
|
2130
|
+
names = []
|
2131
|
+
block.parameters.each {|kind, name| names << name if kind == :key }
|
2132
|
+
return names
|
2133
|
+
end
|
2134
|
+
|
2103
2135
|
def strfold(str, width=80, mark='...')
|
2104
2136
|
#; [!wb7m8] returns string as it is if string is not long.
|
2105
2137
|
return str if str.bytesize <= width
|
@@ -2200,6 +2232,70 @@ END
|
|
2200
2232
|
end
|
2201
2233
|
end
|
2202
2234
|
|
2235
|
+
class PartialRegexp < Regexp
|
2236
|
+
attr_accessor :pattern_string, :begin, :end, :mark
|
2237
|
+
def inspect()
|
2238
|
+
#; [!uyh31] returns function call style string if @pattern_string is set.
|
2239
|
+
if @pattern_string
|
2240
|
+
c = @pattern_string.end_with?("\n") ? "" : ".chomp"
|
2241
|
+
p = @pattern_string.chomp
|
2242
|
+
b = @begin == '\A' ? "'\\A'" : @begin.inspect
|
2243
|
+
e = @end == '\z' ? "'\\z'" : @end.inspect
|
2244
|
+
m = mark == "{== ==}" ? "" : ", #{mark.inspect}"
|
2245
|
+
return "partial_regexp(<<PREXP#{c}, #{b}, #{e}#{m})\n#{p}\nPREXP\n"
|
2246
|
+
#; [!ts9v4] returns regexp literal style string if @pattern_string is not set.
|
2247
|
+
else
|
2248
|
+
s = super
|
2249
|
+
s = s.gsub(/([^\\](?:\\\\)*)((?:\\n)+)/) {
|
2250
|
+
$1 + ("\\n\n" * ($2.length / 2))
|
2251
|
+
}
|
2252
|
+
if s =~ /\n/
|
2253
|
+
s = s.sub(/\A\/(\\A)?/, "/\\1\n")
|
2254
|
+
s = s + "x" # `/.../x` means multiline regexp
|
2255
|
+
end
|
2256
|
+
return s
|
2257
|
+
end
|
2258
|
+
end
|
2259
|
+
end
|
2260
|
+
|
2261
|
+
def partial_regexp!(pattern, begin_='\A', end_='\z', mark="{== ==}")
|
2262
|
+
#; [!peyu4] returns PartialRegexp object which inspect string is function call styel.
|
2263
|
+
regexp = partial_regexp(pattern, begin_, end_, mark)
|
2264
|
+
regexp.pattern_string = pattern
|
2265
|
+
regexp.begin = begin_; regexp.end = end_; regexp.mark = mark
|
2266
|
+
return regexp
|
2267
|
+
end
|
2268
|
+
|
2269
|
+
def partial_regexp(pattern, begin_='\A', end_='\z', mark="{== ==}")
|
2270
|
+
mark_rexp = PARTIAL_REGEXP_CACHE[mark]
|
2271
|
+
if mark_rexp.nil?
|
2272
|
+
#; [!ostkw] raises error if mark has no space or has more than two spaces.
|
2273
|
+
pair = mark.split()
|
2274
|
+
pair.length == 2 or
|
2275
|
+
raise ArgumentError.new("#{mark.inspect}: mark should contain only one space (ex: `{== ==}`).")
|
2276
|
+
open = Regexp.escape(pair[0])
|
2277
|
+
close = Regexp.escape(pair[1])
|
2278
|
+
mark_rexp = Regexp.compile("#{open}(.*?)#{close}")
|
2279
|
+
PARTIAL_REGEXP_CACHE[mark] = mark_rexp
|
2280
|
+
end
|
2281
|
+
#; [!wn524] returns PartialRegexp object which inspect string is regexp literal style.
|
2282
|
+
pos = 0
|
2283
|
+
buf = []
|
2284
|
+
buf << begin_ if begin_
|
2285
|
+
pattern.scan(mark_rexp) do
|
2286
|
+
m = Regexp.last_match
|
2287
|
+
text = pattern[pos, m.begin(0) - pos]
|
2288
|
+
buf << Regexp.escape(text) << $1.strip()
|
2289
|
+
pos = m.end(0)
|
2290
|
+
end
|
2291
|
+
rest = pos == 0 ? pattern : pattern[pos..-1]
|
2292
|
+
buf << Regexp.escape(rest) unless rest.empty?
|
2293
|
+
buf << end_ if end_
|
2294
|
+
return PartialRegexp.compile(buf.join())
|
2295
|
+
end
|
2296
|
+
|
2297
|
+
PARTIAL_REGEXP_CACHE = {} # :nodoc:
|
2298
|
+
|
2203
2299
|
end
|
2204
2300
|
|
2205
2301
|
|
@@ -2342,24 +2438,35 @@ END
|
|
2342
2438
|
module_function
|
2343
2439
|
|
2344
2440
|
def normal s; return s; end
|
2345
|
-
def bold s; return "\e[0;1m#{s}\e[
|
2346
|
-
|
2347
|
-
def
|
2348
|
-
def
|
2349
|
-
def
|
2350
|
-
def
|
2351
|
-
def
|
2352
|
-
def
|
2353
|
-
def
|
2441
|
+
def bold s; return "\e[0;1m#{s}\e[0m"; end
|
2442
|
+
|
2443
|
+
def black s; return "\e[0;30m#{s}\e[0m"; end
|
2444
|
+
def red s; return "\e[0;31m#{s}\e[0m"; end
|
2445
|
+
def green s; return "\e[0;32m#{s}\e[0m"; end
|
2446
|
+
def yellow s; return "\e[0;33m#{s}\e[0m"; end
|
2447
|
+
def blue s; return "\e[0;34m#{s}\e[0m"; end
|
2448
|
+
def magenta s; return "\e[0;35m#{s}\e[0m"; end
|
2449
|
+
def cyan s; return "\e[0;36m#{s}\e[0m"; end
|
2450
|
+
def white s; return "\e[0;37m#{s}\e[0m"; end
|
2451
|
+
|
2452
|
+
def black_b s; return "\e[1;30m#{s}\e[0m"; end # bold
|
2453
|
+
def red_b s; return "\e[1;31m#{s}\e[0m"; end # bold
|
2454
|
+
def green_b s; return "\e[1;32m#{s}\e[0m"; end # bold
|
2455
|
+
def yellow_b s; return "\e[1;33m#{s}\e[0m"; end # bold
|
2456
|
+
def blue_b s; return "\e[1;34m#{s}\e[0m"; end # bold
|
2457
|
+
def magenta_b s; return "\e[1;35m#{s}\e[0m"; end # bold
|
2458
|
+
def cyan_b s; return "\e[1;36m#{s}\e[0m"; end # bold
|
2459
|
+
def white_b s; return "\e[1;37m#{s}\e[0m"; end # bold
|
2354
2460
|
|
2355
2461
|
def topic s; Config.color_enabled ? bold(s) : s; end
|
2356
2462
|
def spec s; Config.color_enabled ? normal(s) : s; end
|
2357
|
-
def pass s; Config.color_enabled ?
|
2463
|
+
def pass s; Config.color_enabled ? cyan(s) : s; end
|
2358
2464
|
def fail s; Config.color_enabled ? red(s) : s; end
|
2359
|
-
def error s; Config.color_enabled ?
|
2465
|
+
def error s; Config.color_enabled ? red_b(s) : s; end # bold
|
2360
2466
|
def skip s; Config.color_enabled ? yellow(s) : s; end
|
2361
2467
|
def todo s; Config.color_enabled ? yellow(s) : s; end
|
2362
2468
|
def reason s; Config.color_enabled ? yellow(s) : s; end
|
2469
|
+
def errmsg s; Config.color_enabled ? red(s) : s; end
|
2363
2470
|
|
2364
2471
|
def status(status, s)
|
2365
2472
|
#; [!yev5y] returns string containing color escape sequence.
|
@@ -2494,6 +2601,11 @@ END
|
|
2494
2601
|
color_enabled = nil
|
2495
2602
|
opts = Options.new
|
2496
2603
|
parser = option_parser(opts)
|
2604
|
+
#; [!v5xie] parses $OKTEST_RB environment variable.
|
2605
|
+
if ENV.key?('OKTEST_RB')
|
2606
|
+
parser.parse(ENV['OKTEST_RB'].split())
|
2607
|
+
end
|
2608
|
+
#
|
2497
2609
|
filenames = parser.parse(args)
|
2498
2610
|
#; [!9973n] '-h' or '--help' option prints help message.
|
2499
2611
|
if opts.help
|
@@ -2505,8 +2617,8 @@ END
|
|
2505
2617
|
puts VERSION
|
2506
2618
|
return 0
|
2507
2619
|
end
|
2508
|
-
#; [!dk8eg] '-
|
2509
|
-
if opts.
|
2620
|
+
#; [!dk8eg] '-S' or '--skeleton' option prints test code skeleton.
|
2621
|
+
if opts.skeleton
|
2510
2622
|
print SKELETON
|
2511
2623
|
return 0
|
2512
2624
|
end
|
@@ -2565,7 +2677,7 @@ END
|
|
2565
2677
|
private
|
2566
2678
|
|
2567
2679
|
class Options #:nodoc:
|
2568
|
-
attr_accessor :help, :version, :style, :filter, :color, :
|
2680
|
+
attr_accessor :help, :version, :style, :filter, :color, :skeleton, :generate, :faster
|
2569
2681
|
end
|
2570
2682
|
|
2571
2683
|
def option_parser(opts)
|
@@ -2592,7 +2704,7 @@ END
|
|
2592
2704
|
#; [!dptgn] '--color' is same as '--color=on'.
|
2593
2705
|
opts.color = val || 'on'
|
2594
2706
|
}
|
2595
|
-
parser.on('-
|
2707
|
+
parser.on('-S', '--skeleton') { opts.skeleton = true }
|
2596
2708
|
parser.on('-G', '--generate[=styleoption]') {|val|
|
2597
2709
|
val.nil? || val == 'unaryop' or
|
2598
2710
|
raise OptionParser::InvalidArgument, val
|
@@ -2607,16 +2719,16 @@ END
|
|
2607
2719
|
return HELP_MESSAGE % {command: command}
|
2608
2720
|
end
|
2609
2721
|
|
2610
|
-
HELP_MESSAGE = <<'END'
|
2722
|
+
HELP_MESSAGE = <<'END'.gsub(/^#.*\n/, '')
|
2611
2723
|
Usage: %{command} [<options>] [<file-or-directory>...]
|
2612
2724
|
-h, --help : show help
|
2613
2725
|
--version : print version
|
2614
2726
|
-s <REPORT-STYLE> : verbose/simple/compact/plain/quiet, or v/s/c/p/q
|
2615
2727
|
-F <PATTERN> : filter topic or spec with pattern (see below)
|
2616
2728
|
--color[={on|off}] : enable/disable output coloring forcedly
|
2617
|
-
-
|
2729
|
+
-S, --skeleton : print test code skeleton
|
2618
2730
|
-G, --generate : generate test code skeleton from ruby file
|
2619
|
-
--faster : make 'ok{}' faster (for very large project)
|
2731
|
+
# --faster : make 'ok{}' faster (for very large project)
|
2620
2732
|
|
2621
2733
|
Filter examples:
|
2622
2734
|
$ oktest -F topic=Hello # filter by topic
|
data/oktest.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
3
|
###
|
4
|
-
### $Release: 1.
|
4
|
+
### $Release: 1.2.0 $
|
5
5
|
### $License: MIT License $
|
6
6
|
### $Copyright: copyright(c) 2011-2021 kuwata-lab.com all rights reserved $
|
7
7
|
###
|
@@ -13,7 +13,7 @@ Gem::Specification.new do |s|
|
|
13
13
|
s.name = "oktest"
|
14
14
|
s.author = "kwatch"
|
15
15
|
s.email = "kwatch@gmail.com"
|
16
|
-
s.version = "$Release: 1.
|
16
|
+
s.version = "$Release: 1.2.0 $".split()[1]
|
17
17
|
s.license = "MIT"
|
18
18
|
s.platform = Gem::Platform::RUBY
|
19
19
|
s.homepage = "https://github.com/kwatch/oktest/tree/ruby"
|
@@ -30,7 +30,7 @@ Oktest.rb is a new-style testing library for Ruby.
|
|
30
30
|
|
31
31
|
See https://github.com/kwatch/oktest/tree/ruby/ruby for details.
|
32
32
|
END
|
33
|
-
s.required_ruby_version = ">= 2.
|
33
|
+
s.required_ruby_version = ">= 2.0"
|
34
34
|
s.add_dependency "diff-lcs", "~> 1.0"
|
35
35
|
s.add_dependency "benry-recorder", "~> 1.0"
|
36
36
|
|
data/test/assertion_test.rb
CHANGED
data/test/filter_test.rb
CHANGED
data/test/fixture_test.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
3
|
###
|
4
|
-
### $Release: 1.
|
4
|
+
### $Release: 1.2.0 $
|
5
5
|
### $Copyright: copyright(c) 2011-2021 kuwata-lab.com all rights reserved $
|
6
6
|
### $License: MIT License $
|
7
7
|
###
|
@@ -116,6 +116,19 @@ END
|
|
116
116
|
assert_eq sout, expected
|
117
117
|
end
|
118
118
|
|
119
|
+
it "[!gyyst] overwrites keyword params by fixture values." do
|
120
|
+
Oktest.scope do
|
121
|
+
topic "topic#1" do
|
122
|
+
fixture(:x) {|y, z: 3| {y: y, z: z} }
|
123
|
+
fixture(:y) { 2 }
|
124
|
+
spec("not overwrite") {|x| p x }
|
125
|
+
spec("overwrite", fixture: {y: 4, z: 5}) {|x| p x }
|
126
|
+
end
|
127
|
+
end
|
128
|
+
sout = run_all()
|
129
|
+
assert_eq sout, "{:y=>2, :z=>3}\n{:y=>4, :z=>5}\n"
|
130
|
+
end
|
131
|
+
|
119
132
|
it "[!4xghy] calls fixture block with context object as self." do
|
120
133
|
Oktest.scope do
|
121
134
|
topic "Parent" do
|
data/test/generator_test.rb
CHANGED
data/test/helper_test.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
###
|
2
|
-
### $Release: 1.
|
2
|
+
### $Release: 1.2.0 $
|
3
3
|
### $Copyright: copyright(c) 2011-2021 kuwata-lab.com all rights reserved $
|
4
4
|
### $License: MIT License $
|
5
5
|
###
|
@@ -36,7 +36,7 @@ class SpecHelper_TC < TC
|
|
36
36
|
it "[!bc3l2] records invoked location." do
|
37
37
|
lineno = __LINE__ + 1
|
38
38
|
o = ok {"bar"}
|
39
|
-
assert o.location.start_with?("#{__FILE__}:#{lineno}:")
|
39
|
+
assert o.location.to_s.start_with?("#{__FILE__}:#{lineno}:")
|
40
40
|
end
|
41
41
|
it "[!mqtdy] not record invoked location when `Config.ok_location == false`." do
|
42
42
|
bkup = Oktest::Config.ok_location
|
@@ -60,7 +60,7 @@ class SpecHelper_TC < TC
|
|
60
60
|
it "[!agmx8] records invoked location." do
|
61
61
|
lineno = __LINE__ + 1
|
62
62
|
o = not_ok {"bar"}
|
63
|
-
assert o.location.start_with?("#{__FILE__}:#{lineno}:")
|
63
|
+
assert o.location.to_s.start_with?("#{__FILE__}:#{lineno}:")
|
64
64
|
end
|
65
65
|
it "[!a9508] not record invoked location when `Config.ok_location == false`." do
|
66
66
|
bkup = Oktest::Config.ok_location
|