whitestone 1.0.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/.gitignore +1 -0
- data/Gemfile +4 -0
- data/LICENSE +16 -0
- data/README.txt +78 -0
- data/Rakefile +1 -0
- data/bin/whitestone +263 -0
- data/doc/README-snippets.rdoc +58 -0
- data/doc/whitestone.markdown +806 -0
- data/etc/aliases +5 -0
- data/etc/examples/example_1.rb +51 -0
- data/etc/examples/example_2.rb +51 -0
- data/etc/extra_tests/basic.rb +56 -0
- data/etc/extra_tests/error_should_not_also_fail.rb +17 -0
- data/etc/extra_tests/output_examples.rb +108 -0
- data/etc/extra_tests/output_examples_code.rb +38 -0
- data/etc/extra_tests/raise.rb +4 -0
- data/etc/extra_tests/realistic_example.rb +94 -0
- data/etc/extra_tests/specification_error.rb +8 -0
- data/etc/extra_tests/stop.rb +16 -0
- data/etc/extra_tests/terminate_suite.rb +56 -0
- data/etc/run-output-examples +1 -0
- data/etc/run-unit-tests +1 -0
- data/etc/ws +1 -0
- data/lib/whitestone.rb +710 -0
- data/lib/whitestone/assertion_classes.rb +418 -0
- data/lib/whitestone/auto.rb +20 -0
- data/lib/whitestone/custom_assertions.rb +252 -0
- data/lib/whitestone/include.rb +14 -0
- data/lib/whitestone/output.rb +335 -0
- data/lib/whitestone/support.rb +29 -0
- data/lib/whitestone/version.rb +3 -0
- data/test/_setup.rb +5 -0
- data/test/custom_assertions.rb +120 -0
- data/test/insulation.rb +202 -0
- data/test/whitestone_test.rb +616 -0
- data/whitestone.gemspec +31 -0
- metadata +125 -0
data/etc/aliases
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
|
2
|
+
# This example runs some tests against the Date class. All of them pass.
|
3
|
+
# The Date class is large and complex; this barely scratches the surface.
|
4
|
+
|
5
|
+
require 'date'
|
6
|
+
|
7
|
+
D "Date" do
|
8
|
+
|
9
|
+
D.< { # setup for each block
|
10
|
+
@d = Date.new(1972, 5, 13)
|
11
|
+
}
|
12
|
+
|
13
|
+
D "#to_s" do
|
14
|
+
Eq @d.to_s, "1972-05-13"
|
15
|
+
end
|
16
|
+
|
17
|
+
D "#next" do
|
18
|
+
end_of_april = Date.new(2010, 4, 30)
|
19
|
+
start_of_may = Date.new(2010, 5, 1)
|
20
|
+
T { end_of_april.next == start_of_may }
|
21
|
+
end
|
22
|
+
|
23
|
+
D "day, month, year, week, day-of-year, etc." do
|
24
|
+
|
25
|
+
D.< { :extra_setup_for_these_three_blocks_if_required }
|
26
|
+
|
27
|
+
D "civil" do
|
28
|
+
Eq @d.year, 1972
|
29
|
+
Eq @d.month, 5
|
30
|
+
Eq @d.day, 13
|
31
|
+
end
|
32
|
+
D "commercial" do
|
33
|
+
Eq @d.cwyear, 1972
|
34
|
+
Eq @d.cweek, 19 # Commercial week-of-year
|
35
|
+
Eq @d.cwday, 6 # Commercial day-of-week (6 = Sat)
|
36
|
+
end
|
37
|
+
D "ordinal" do
|
38
|
+
Eq @d.yday, 134 # 134th day of the year
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
D "#leap?" do
|
43
|
+
[1984, 2000, 2400].each do |year|
|
44
|
+
T { Date.new(year, 6, 27).leap? }
|
45
|
+
end
|
46
|
+
[1900, 2007, 2100, 2401].each do |year|
|
47
|
+
F { Date.new(year, 12, 3).leap? }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
|
2
|
+
# This example is the same as Example 1, except that some bugs have
|
3
|
+
# been introduced into the test code so that some assertions will fail.
|
4
|
+
|
5
|
+
require 'date'
|
6
|
+
|
7
|
+
D "Date" do
|
8
|
+
|
9
|
+
D.< { # setup for each block
|
10
|
+
@d = Date.new(1972, 5, 13)
|
11
|
+
}
|
12
|
+
|
13
|
+
D "#to_s" do
|
14
|
+
Eq @d.to_s, "1972-5-13"
|
15
|
+
end
|
16
|
+
|
17
|
+
D "#next" do
|
18
|
+
end_of_april = Date.new(2010, 4, 30)
|
19
|
+
start_of_may = Date.new(2010, 6, 1)
|
20
|
+
T { end_of_april.next == start_of_may }
|
21
|
+
end
|
22
|
+
|
23
|
+
D "day, month, year, week, day-of-year, etc." do
|
24
|
+
|
25
|
+
D.< { :extra_setup_for_these_three_blocks_if_required }
|
26
|
+
|
27
|
+
D "civil" do
|
28
|
+
Eq @d.year, 1972
|
29
|
+
Eq @d.month, 5
|
30
|
+
Eq @d.day, 13
|
31
|
+
end
|
32
|
+
D "commercial" do
|
33
|
+
Eq @d.cwyear, 1972
|
34
|
+
Eq @d.cweek, 13 # Commercial week-of-year
|
35
|
+
Eq @d.cwday, 6 # Commercial day-of-week (6 = Sat)
|
36
|
+
end
|
37
|
+
D "ordinal" do
|
38
|
+
Eq @d.day_of_year, 134 # 134th day of the year
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
D "#leap?" do
|
43
|
+
[1984, 2000, 2400].each do |year|
|
44
|
+
T { Date.new(year, 6, 27).leap? }
|
45
|
+
end
|
46
|
+
[1900, 2007, 2100, 2401].each do |year|
|
47
|
+
F { Date.new(year, 12, 3).leap? }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
|
2
|
+
D "Whitestone.action" do
|
3
|
+
T { Whitestone.action :Eq, :query, 4, 4 }
|
4
|
+
T { Whitestone.action :T, :query, :foo }
|
5
|
+
T { Whitestone.action(:T, :query) { :foo } }
|
6
|
+
end
|
7
|
+
|
8
|
+
def this_method_will_raise_an_error
|
9
|
+
raise StandardError, "Sample error"
|
10
|
+
end
|
11
|
+
|
12
|
+
def this_one_wont
|
13
|
+
:foo
|
14
|
+
end
|
15
|
+
|
16
|
+
def throws_foo
|
17
|
+
throw :foo
|
18
|
+
end
|
19
|
+
|
20
|
+
def doesnt_throw_foo
|
21
|
+
:noop
|
22
|
+
end
|
23
|
+
|
24
|
+
def specific_error(sym)
|
25
|
+
case sym
|
26
|
+
when :type then raise TypeError
|
27
|
+
when :run then raise RuntimeError
|
28
|
+
when :range then raise RangeError
|
29
|
+
when :io then raise IOError
|
30
|
+
else raise ArgumentError
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
D "Basic tests" do
|
35
|
+
x = 2 + 2
|
36
|
+
T { x == 4 }
|
37
|
+
T! { x == 5 }
|
38
|
+
F { x == 5 }
|
39
|
+
F! { x == 4 }
|
40
|
+
N { "foo".index("z") }
|
41
|
+
N! { "foo".index("o") }
|
42
|
+
Eq x, 4
|
43
|
+
Eq! x, 5
|
44
|
+
Mt /(an){2}/, "banana"
|
45
|
+
Mt! /(an){3}/, "banana"
|
46
|
+
E { this_method_will_raise_an_error }
|
47
|
+
E! { this_one_wont }
|
48
|
+
E!(RangeError) { this_one_wont }
|
49
|
+
E() { specific_error(:run) }
|
50
|
+
E(RuntimeError) { specific_error(:run) }
|
51
|
+
E(RuntimeError, IOError) { specific_error(:run) }
|
52
|
+
C(:foo) { throws_foo }
|
53
|
+
C!(:foo) { doesnt_throw_foo }
|
54
|
+
|
55
|
+
E!() { specific_error(:io) }
|
56
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
|
2
|
+
def some_method(n)
|
3
|
+
raise ArgumentError unless n > 0
|
4
|
+
n
|
5
|
+
end
|
6
|
+
|
7
|
+
D "An error should not also fail" do
|
8
|
+
## The following call should result in ERROR and not an additional FAIL.
|
9
|
+
## (This is therefore not a unit test, really; it's designed to error out...)
|
10
|
+
T { this_method_does_not_exist(:foo) }
|
11
|
+
|
12
|
+
## This test works
|
13
|
+
Eq some_method(5), 5
|
14
|
+
|
15
|
+
## This test errors out
|
16
|
+
Eq some_method(-5), -5
|
17
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
|
2
|
+
# The examples here are designed to demonstrate that all the different ways of
|
3
|
+
# failing (T, F, N, Eq, Mt, E, C) produce good output.
|
4
|
+
#
|
5
|
+
# Some of the tests will pass; some will fail; some will raise an error.
|
6
|
+
#
|
7
|
+
# The output doesn't make pretty reading, but it's a way to look for poor
|
8
|
+
# formatting or inconsistent colour or less-than-helpful error messages.
|
9
|
+
|
10
|
+
load "#{Dir.pwd}/etc/extra_tests/output_examples_code.rb"
|
11
|
+
|
12
|
+
D 'Vanilla assertion failure' do
|
13
|
+
T { prime? 64 }
|
14
|
+
end
|
15
|
+
|
16
|
+
D "Attempt to open file that doesn't exist" do
|
17
|
+
T { count_lines_in_file("fdsjhfaksljdfhakljshdf.txt") == 492 }
|
18
|
+
end
|
19
|
+
|
20
|
+
D 'Expected error to be raised but it didn\'t happen (default: StandardError)' do
|
21
|
+
E { prime? 13 }
|
22
|
+
end
|
23
|
+
|
24
|
+
D "Expected error to be raised but it didn't happen (specify errors)" do
|
25
|
+
E(ArgumentError, NameError) { prime? 99 }
|
26
|
+
end
|
27
|
+
|
28
|
+
D "Expect NameError to be raised but it's not NameError; it's Errno::ENOENT" do
|
29
|
+
E(NameError) { count_lines_in_file("fdsjhfakslljshdf.txt") }
|
30
|
+
end
|
31
|
+
|
32
|
+
D 'Expect no error to occur, but one does' do
|
33
|
+
E! { count_lines_in_file("fdsjhfaksljdfhakljshdf.txt") }
|
34
|
+
end
|
35
|
+
|
36
|
+
D 'Failure to catch appropriate symbol' do
|
37
|
+
C(:something) { Dir.entries('.') }
|
38
|
+
end
|
39
|
+
|
40
|
+
D 'Expected :even not to be thrown but it was' do
|
41
|
+
C!(:even) { even_or_odd(12) }
|
42
|
+
end
|
43
|
+
|
44
|
+
D 'Error raised while trying to catch a symbol' do
|
45
|
+
C(:foo) { count_lines_in_file("fdsjhfakshakljshdf.txt") }
|
46
|
+
end
|
47
|
+
|
48
|
+
D 'Test prime?' do
|
49
|
+
T { prime? 43 }
|
50
|
+
F { prime? 1 }
|
51
|
+
E { prime? 450 }
|
52
|
+
E { prime? 41.9 }
|
53
|
+
E!{ prime? 35 }
|
54
|
+
end
|
55
|
+
|
56
|
+
D 'Test even_or_odd' do
|
57
|
+
C(:even) { even_or_odd(148) }
|
58
|
+
C(:odd) { even_or_odd(9313) }
|
59
|
+
end
|
60
|
+
|
61
|
+
D 'Straightforward equality failure (positive)' do
|
62
|
+
array = (1...10).to_a
|
63
|
+
Eq array.size, 10
|
64
|
+
end
|
65
|
+
|
66
|
+
D 'Straightforward equality failure (negative)' do
|
67
|
+
Eq! "\n\t text \r \n".strip, "text"
|
68
|
+
end
|
69
|
+
|
70
|
+
D 'Test simple_html; demonstrates string difference' do
|
71
|
+
text = "I _must_ go down to the *seas* again\nTo the @lonely@ sea and the sky"
|
72
|
+
Eq simple_html(text),
|
73
|
+
"<p>I <em>must</em> go down to <strong>seas</strong> again\nTo the " +
|
74
|
+
"<code>lonely</code> sea and the skies</p>"
|
75
|
+
end
|
76
|
+
|
77
|
+
D 'Regular expression matching (positive)' do
|
78
|
+
Mt "Smith, John: (02) 9481 1111", /^[A-z0-9]+$/
|
79
|
+
end
|
80
|
+
|
81
|
+
D 'Regular expression matching (negative)' do
|
82
|
+
Mt! "Doe, Jane: (07) 131 008", /Jane/
|
83
|
+
end
|
84
|
+
|
85
|
+
D 'Expecting something to be nil' do
|
86
|
+
N [25, 32, 7, 51].find { |n| prime? n }
|
87
|
+
end
|
88
|
+
|
89
|
+
D 'Expecting something not to be nil' do
|
90
|
+
N! { "foo".index('t') }
|
91
|
+
end
|
92
|
+
|
93
|
+
D 'Identity (positive)' do
|
94
|
+
Id "foo", "foo"
|
95
|
+
end
|
96
|
+
|
97
|
+
D 'Identity (negative)' do
|
98
|
+
array = (1..10).to_a
|
99
|
+
Id! array, array
|
100
|
+
end
|
101
|
+
|
102
|
+
D 'Float equality (positive)' do
|
103
|
+
Ft 3.14, Math::PI
|
104
|
+
end
|
105
|
+
|
106
|
+
D 'Float equality (negative)' do
|
107
|
+
Ft! 3.141592654, Math::PI
|
108
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
|
2
|
+
# Used to test 'catch'
|
3
|
+
def even_or_odd(n)
|
4
|
+
if n % 2 == 1
|
5
|
+
throw :odd
|
6
|
+
else
|
7
|
+
throw :even
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# Used to generate errors (file not found).
|
12
|
+
def count_lines_in_file(path)
|
13
|
+
File.readlines(path).size
|
14
|
+
end
|
15
|
+
|
16
|
+
# Used for assertions and error raising.
|
17
|
+
def prime?(n)
|
18
|
+
unless (1..100).include? n
|
19
|
+
raise ArgumentError, "Argument to prime? must be in range (1..100): #{n}"
|
20
|
+
end
|
21
|
+
unless Integer === n
|
22
|
+
raise ArgumentError, "Argument to prime? must be an integer: #{n}"
|
23
|
+
end
|
24
|
+
return false if n == 1
|
25
|
+
(2..Math.sqrt(n).to_i).map { |i| n % i }.all? { |rem| rem != 0 }
|
26
|
+
end
|
27
|
+
|
28
|
+
# Used to test string equality and demonstrate string difference.
|
29
|
+
# Surround with <p>, implement _word_, *word* and @word@. Remove newlines.
|
30
|
+
def simple_html(string)
|
31
|
+
tag = lambda { |str, t| "<#{t}>#{str}</#{t}>" }
|
32
|
+
html = string.
|
33
|
+
gsub(/_(\w+)_/) { tag[$1, :em] }.
|
34
|
+
gsub(/\*(\w+)\*/) { tag[$1, :strong] }.
|
35
|
+
gsub(/@(\w+)@/) { tag[$1, :code] }.
|
36
|
+
gsub(/\r?\n/, ' ')
|
37
|
+
tag[html, :p]
|
38
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
|
2
|
+
# This file contains a realistic example of unit testing using whitestone.
|
3
|
+
# The code contains bugs which the tests reveal.
|
4
|
+
|
5
|
+
# - something with a complex #inspect and/or #to_s (or perhaps #html)
|
6
|
+
# - something that takes direct input and gives direct output
|
7
|
+
# (i.e. no need for reading file or interacting with other objects)
|
8
|
+
# - something involving some parsing, like RGeom's types
|
9
|
+
# - something involving a data store (index), especially if it means
|
10
|
+
# that setup is required before the tests
|
11
|
+
# - add_xxx(...)
|
12
|
+
# - maybe take a test from an existing project (RubyGems?) and convert
|
13
|
+
# it to whitestone
|
14
|
+
# - RGeom::Label ?
|
15
|
+
# - RGeom::Point, modified to store points like :A itself ?
|
16
|
+
# - and RGeom::Vertex to boot?
|
17
|
+
# - something that takes a nested data structure (arrays inside hashes
|
18
|
+
# inside...) and generates meaningful summary data
|
19
|
+
# - look at existing unit testing tutorials on the net
|
20
|
+
# - found nothing
|
21
|
+
# - something in standard library ?
|
22
|
+
# - extend Date with some Duration-type methods ?
|
23
|
+
# - some extensions to core classes, taken from 'extensions' ?
|
24
|
+
|
25
|
+
# p1 = Point.new(5, -2)
|
26
|
+
# p2 = Point.polar(11, 30)
|
27
|
+
# Point[:A] = p1
|
28
|
+
# Point[:B] = p2
|
29
|
+
# Point[:A] # -> p1
|
30
|
+
class Point
|
31
|
+
@@index = Hash.new
|
32
|
+
def initialize(x, y)
|
33
|
+
@x, @y = x, y
|
34
|
+
end
|
35
|
+
def Point.cartesian(x, y)
|
36
|
+
Point.new(x, y)
|
37
|
+
end
|
38
|
+
def Point.polar(r, th)
|
39
|
+
Point.new(r * Math.cos(th), r * Math.sin(th))
|
40
|
+
end
|
41
|
+
def Point.[](symbol)
|
42
|
+
@@index[symbol]
|
43
|
+
end
|
44
|
+
def Point.[]=(symbol, point)
|
45
|
+
@@index[symbol] = point
|
46
|
+
end
|
47
|
+
def polar
|
48
|
+
r = Math.sqrt(x**2 + y**2)
|
49
|
+
th = Math.atan2(y, x)
|
50
|
+
[r, th]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
#
|
56
|
+
# Simple markup function to turn formatted text into HTML:
|
57
|
+
# * Implement _word_, *word* and @word@ (em, strong and code, respectively);
|
58
|
+
# * Surround paragraphs with <p> tags;
|
59
|
+
# * Turn single newlines into spaces.
|
60
|
+
#
|
61
|
+
def simple_markup(string)
|
62
|
+
tag = lambda { |str, t| "<#{t}>#{str}</#{t}>" }
|
63
|
+
html = string.
|
64
|
+
gsub(/_(\w+)_/) { tag[$1, :em] }.
|
65
|
+
gsub(/\*(\W+)\*/) { tag[$1, :strong] }.
|
66
|
+
gsub(/@(\w+)@/) { tag[$1, :code] }.
|
67
|
+
gsub(/(.+?)\n{2,}/) { tag[$1, :p] }.
|
68
|
+
gsub(/\n/, ' ')
|
69
|
+
end
|
70
|
+
|
71
|
+
D "simple_markup" do
|
72
|
+
D "breaks text into paragraphs" do
|
73
|
+
Eq simple_markup("abc"), "<p>abc</p>"
|
74
|
+
Eq simple_markup("abc\n\ndef"), "<p>abc</p><p>def</p>"
|
75
|
+
Eq simple_markup("abc\n\ndef\n\n\n\nghi\n"), "<p>abc</p><p>def</p><p>ghi</p>"
|
76
|
+
end
|
77
|
+
D "replaces single newlines with a space" do
|
78
|
+
Eq simple_markup("abc\ndef"), "<p>abc xyz</p>"
|
79
|
+
Eq simple_markup("abc\ndef\nghi"), "<p>abc xyz ghi</p>"
|
80
|
+
end
|
81
|
+
D "handles mixed paragraphs and single newlines correctly" do
|
82
|
+
text = "Once upon a time\nIn a land far away\n\n" \
|
83
|
+
+ "A frog named Kermit\n\nDecared he was here to stay"
|
84
|
+
html = "<p>Once upon a time In a land far away</p>" \
|
85
|
+
+ "<p>A frog named Kermit Decared he was here to stay</p>"
|
86
|
+
Eq simple_markup(text), html
|
87
|
+
end
|
88
|
+
D "handles _words_" do
|
89
|
+
Eq simple_markup("One _two_ _three_"), "<p>One <em>two</em> <em>three</em></p>"
|
90
|
+
end
|
91
|
+
D "handles *words*" do
|
92
|
+
Eq simple_markup("One *fine* day"), "<p>One <strong>fine</strong> day</p>"
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
D "Whitestone.stop" do
|
2
|
+
D "Benign first test" do
|
3
|
+
T { 1 + 1 == 2 }
|
4
|
+
end
|
5
|
+
D "Here we go" do
|
6
|
+
if defined? Whitestone
|
7
|
+
Whitestone.stop
|
8
|
+
elsif defined? Dfect
|
9
|
+
Dfect.stop
|
10
|
+
end
|
11
|
+
raise "Must not get here"
|
12
|
+
end
|
13
|
+
D "Must not get here" do
|
14
|
+
raise "Must not get here"
|
15
|
+
end
|
16
|
+
end
|