dev-utils 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.
- data/HISTORY.txt +36 -0
- data/MIT-LICENSE.txt +20 -0
- data/README.txt +21 -0
- data/Rakefile +135 -0
- data/VERSION +1 -0
- data/etc/doc/DebuggingAids.textile +450 -0
- data/etc/doc/UnitTestOrganisation.textile +253 -0
- data/etc/doc/generate.rb +187 -0
- data/etc/doc/index.textile +110 -0
- data/etc/doc/links.dat +9 -0
- data/etc/doc/textile.css +150 -0
- data/examples/breakpoint-example.rb +30 -0
- data/examples/debug.log +0 -0
- data/examples/log-trace-example.rb +35 -0
- data/lib/dev-utils/debug.rb +32 -0
- data/lib/dev-utils/debug/diff.rb +187 -0
- data/lib/dev-utils/debug/irb.rb +176 -0
- data/lib/dev-utils/debug/log.rb +107 -0
- data/lib/dev-utils/test.rb +267 -0
- data/test/TEST.rb +6 -0
- data/test/tc_debug.rb +153 -0
- metadata +76 -0
@@ -0,0 +1,253 @@
|
|
1
|
+
|
2
|
+
!header dev-utils/test main
|
3
|
+
|
4
|
+
h1. Unit Test Organisation
|
5
|
+
|
6
|
+
!toc
|
7
|
+
|
8
|
+
<div class="planned">
|
9
|
+
|
10
|
+
(Everything in this section is _planned_ functionality.)
|
11
|
+
|
12
|
+
h2. Introduction
|
13
|
+
|
14
|
+
Unit testing can be a pain to organise.
|
15
|
+
* You have to tell your test code where to find the library code that it's
|
16
|
+
testing.
|
17
|
+
* You need a mechanism for running all your tests at once, but would also like
|
18
|
+
to be able to run just one, or a few.
|
19
|
+
* If the tests need data, you need to organise that as well. Sometimes you
|
20
|
+
need to work on a copy of the data so you don't muck it up for the next
|
21
|
+
test run.
|
22
|
+
|
23
|
+
All of these organisational hassles are dealt with by the @dev-utils/test@
|
24
|
+
package. It provides a method for running your test suite (specifying which
|
25
|
+
tests if you like), which manages the load path. It also provides a method
|
26
|
+
for accessing test data in a flexible way. These only work if you follow some
|
27
|
+
conventions (detailed below). So the final benefit provided by
|
28
|
+
@dev-utils/test@ is a documented approach to managing the unit testing
|
29
|
+
part of any project.
|
30
|
+
|
31
|
+
The whole point of @dev-utils/test@ is to collect a certain unit testing
|
32
|
+
organisation methodology in one place, and make that reusable across projects.
|
33
|
+
This is better than having to roll your own on each new project, usually
|
34
|
+
without a clear strategy.
|
35
|
+
|
36
|
+
This document contains:
|
37
|
+
* the rules for using @dev-utils/test@ with your project;
|
38
|
+
* the @dev-utils/test@ approach in detail;
|
39
|
+
* the ground rules to follow so @dev-utils/test@ can work with your project;
|
40
|
+
* configuration options in case you want to vary some things;
|
41
|
+
* information about the complete sample project included in the distribution.
|
42
|
+
|
43
|
+
p(comment). I'll probably forget about a "complete sample project". It should
|
44
|
+
be easy enough to use without that. Perhaps refer to a live project that uses
|
45
|
+
it.
|
46
|
+
|
47
|
+
|
48
|
+
h2. A @dev-utils/test@ Project: Summary
|
49
|
+
|
50
|
+
Relative to your project's root directory:
|
51
|
+
|
52
|
+
* Library code goes under @lib/@. So when a unit test does @require
|
53
|
+
'projX/init'@, it will be @lib/projX/init.rb@ that is loaded.
|
54
|
+
|
55
|
+
* Unit test files are named, for example, @tc_projX.rb@, and go in @test/@ or
|
56
|
+
a subdirectory.
|
57
|
+
|
58
|
+
* You have a master test file, @test/TEST.rb@, which loads and runs some or
|
59
|
+
all of your unit tests. Writing this file is extremely easy, as
|
60
|
+
@dev-utils/test@ does all the hard work.
|
61
|
+
|
62
|
+
** Running @ruby test/TEST.rb@ is the *only* way to run your unit tests.
|
63
|
+
|
64
|
+
** This program gives you options over which tests are run and how much output
|
65
|
+
is given.
|
66
|
+
|
67
|
+
* Test data (files containing data that are used for unit tests) is located in
|
68
|
+
@test/DATA@ or a subdirectory. Unit tests use a method called @load_data@
|
69
|
+
to access this test data.
|
70
|
+
|
71
|
+
h3. Using Rake to Run Tests
|
72
|
+
|
73
|
+
Pursuant to the running of unit tests via @test/TEST.rb@, here is a Rake task
|
74
|
+
you can set up to run your tests for you.
|
75
|
+
|
76
|
+
<pre>
|
77
|
+
desc "Run unit tests"
|
78
|
+
task :test do
|
79
|
+
exec "ruby test/TEST.rb #{ARGV.join(' ')}"
|
80
|
+
end
|
81
|
+
</pre>
|
82
|
+
|
83
|
+
If that is in your Rakefile, and the Rakefile is in the project's root
|
84
|
+
directory, then you can run @rake test@ from any directory in the project, and
|
85
|
+
your unit tests will run. There are various command-line options you can give
|
86
|
+
to @test/TEST.rb@, as the next section will detail.
|
87
|
+
|
88
|
+
|
89
|
+
h2. A @dev-utils/test@ Project: Detail
|
90
|
+
|
91
|
+
To make use of @dev-utils/test@, this is how you operate. All your
|
92
|
+
unit tests are coded in files like @tc_<i>foo</i>.rb@ in the @test@
|
93
|
+
directory, or subdirectories. There is one master test file
|
94
|
+
@test/TEST.rb@, which will load and run all of the unit test files.
|
95
|
+
Thanks to this package, however, writing that file is easy.
|
96
|
+
|
97
|
+
This is what happens when you run @ruby test/TEST.rb --help@:
|
98
|
+
|
99
|
+
<pre style="font-size:10pt"> Welcome to the dev-utils/test automatic unit test runner. Here are the
|
100
|
+
options:
|
101
|
+
|
102
|
+
-q quiet mode
|
103
|
+
-Q very quiet mode
|
104
|
+
-v verbose mode (default)
|
105
|
+
-s run unit tests in separate test suites
|
106
|
+
-h show help
|
107
|
+
str1 str2 ... run only those tests whose filenames contain str1 or
|
108
|
+
str2 or ...
|
109
|
+
|
110
|
+
For example, to run only those tests whose filenames include "remote" or
|
111
|
+
"db", and to run a separate suite for each test file, and to run in quiet
|
112
|
+
mode:
|
113
|
+
|
114
|
+
ruby test/TEST.rb -q remote db -s
|
115
|
+
</pre>
|
116
|
+
|
117
|
+
As the developer, you don't need to do any programming to make this happen;
|
118
|
+
you just need to create @test/TEST.rb@, in which you call one method.
|
119
|
+
This is what that file looks like:
|
120
|
+
|
121
|
+
<pre>
|
122
|
+
require 'rubygems'
|
123
|
+
require 'dev-utils/test'
|
124
|
+
|
125
|
+
DevUtils::Test.load_tests(__FILE__, *ARGV)
|
126
|
+
</pre>
|
127
|
+
|
128
|
+
As a sneak peek behind the scenes, @load_tests@ uses <code>__FILE__</code> to
|
129
|
+
orient itself, using default values to locate the @lib@ directory (so it can
|
130
|
+
manipulate the Ruby load path), and the @DATA@ directory (so calls to
|
131
|
+
@load_data@ will work).
|
132
|
+
|
133
|
+
So far, we have covered two of the three organisational hassles listed in the
|
134
|
+
introduction. The remaining one is managing test data. This is handled by
|
135
|
+
the @load_data@ method.
|
136
|
+
|
137
|
+
All your test data is contained in files underneath the @test/DATA@
|
138
|
+
directory. You use the path to those files (relative to @test/DATA@)
|
139
|
+
to identify the data file you want to load. Simple enough. So a unit test
|
140
|
+
for an email reader might look like this:
|
141
|
+
|
142
|
+
<pre>
|
143
|
+
def test_sender_extraction
|
144
|
+
input = Test.load_data('bulk/emails.txt')
|
145
|
+
output = EmailParser.parse(input)
|
146
|
+
assert_equal(...)
|
147
|
+
end
|
148
|
+
</pre>
|
149
|
+
|
150
|
+
In that case, the data in the @test/DATA/bulk/emails.txt@ file was served up
|
151
|
+
as a String. But @load_data@ is more flexible than that. It defaults to
|
152
|
+
returning a String, but can return a File (opened for reading) or a Pathname
|
153
|
+
instead. Also, it can make a copy of the file (to a temporary place) and
|
154
|
+
point you to that.
|
155
|
+
|
156
|
+
So a unit test that is modifying an SQLite database might look like this:
|
157
|
+
|
158
|
+
<pre>
|
159
|
+
def test_database_modification
|
160
|
+
dbfile = Test.load_data('customers3.db', :pathname, :copy)
|
161
|
+
init_system(dbfile)
|
162
|
+
...
|
163
|
+
end
|
164
|
+
</pre>
|
165
|
+
|
166
|
+
The above code uses <i>@Test@</i> instead of <i>@DevUtils::Test@</i>
|
167
|
+
because it is assumed that an @include DevUtils@ was performed in the
|
168
|
+
test class.
|
169
|
+
|
170
|
+
|
171
|
+
h3. Consequences
|
172
|
+
|
173
|
+
The consequence of writing unit tests using @dev-utils/test@ is that they
|
174
|
+
cannot be run directly. Unit tests are written _assuming_ that they can find
|
175
|
+
the right library file in the load path. Without being run through
|
176
|
+
@test/TEST.rb@, this assumption does not (necessarily) hold.
|
177
|
+
|
178
|
+
And if a unit test calls @load_data@ without the initialization step that
|
179
|
+
@load_tests@ provides (or without explicit initialization - see below), then
|
180
|
+
that data will not be found.
|
181
|
+
|
182
|
+
|
183
|
+
h2. Ground Rules
|
184
|
+
|
185
|
+
<b><i>The information here has been effectively stated in the Summary section
|
186
|
+
above. Get rid of this.</i></b>
|
187
|
+
|
188
|
+
In order to benefit from these unit testing features, you must follow some
|
189
|
+
conventions in the way you organise your project and write your code. If your
|
190
|
+
project is called @projectX@, then this is how it should be organised:
|
191
|
+
|
192
|
+
* The unit tests themselves are named @tc_<i>foo</i>.rb@, and are
|
193
|
+
located under the @projectX/test@ directory. The name of that
|
194
|
+
directory doesn't matter, but we're assuming that for the following points.
|
195
|
+
|
196
|
+
* The master test runner is @projectX/test/TEST.rb@. Unit tests are
|
197
|
+
*always* run through this program. It contains the code shown in the
|
198
|
+
previous section.
|
199
|
+
|
200
|
+
* The library code goes in @projectX/lib/...@. Observing this
|
201
|
+
convention means that @load_tests@ knows where to find the library code that
|
202
|
+
is being tested.
|
203
|
+
|
204
|
+
* If the tests make use of data files, those files are located in the
|
205
|
+
@projectX/test/DATA@ directory. This way, the default will work and
|
206
|
+
the @load_tests@ method above will set the data directory correctly.
|
207
|
+
|
208
|
+
* ...
|
209
|
+
|
210
|
+
|
211
|
+
h2. Configurations
|
212
|
+
|
213
|
+
If you want the test data directory to be something other than
|
214
|
+
@test/DATA@, or you want the lib directory to be something other than
|
215
|
+
@lib@ (both relative to the root directory of the project), then the
|
216
|
+
following methods are available to you:
|
217
|
+
* @DevUtils::Test.project_dir = ...@
|
218
|
+
* @DevUtils::Test.set_project_dir_from(path, project_name)@
|
219
|
+
* @DevUtils::Test.lib_dir = ...@
|
220
|
+
* @DevUtils::Test.test_dir = ...@
|
221
|
+
* @DevUtils::Test.data_dir = ...@
|
222
|
+
|
223
|
+
If you want to specify any of them, then you *must* specify the project
|
224
|
+
directory first, as all the others are interpreted relative to that. Also,
|
225
|
+
these directories must be specified _before_ you call @load_tests@. Really,
|
226
|
+
the only appropriate place for any of this is @test/TEST.rb@.
|
227
|
+
|
228
|
+
p. @set_project_dir_from@ is the easier way to set the project directly. If you
|
229
|
+
use @project_dir=@ instead, _make sure_ you specify an absolute path (_I think
|
230
|
+
that requirement still stands..._).
|
231
|
+
|
232
|
+
Here is an example of a @unit-tests/run_tests.rb@ file with full
|
233
|
+
customisation. The name of the project is @projectX@.
|
234
|
+
|
235
|
+
<pre>
|
236
|
+
require 'rubygems'
|
237
|
+
require 'dev-utils/test'
|
238
|
+
include DevUtils
|
239
|
+
|
240
|
+
Test.set_project_dir_from(__FILE__, "projectX")
|
241
|
+
Test.lib_dir = "."
|
242
|
+
Test.test_dir = "unit-tests"
|
243
|
+
Test.data_dir = "etc/test-data"
|
244
|
+
|
245
|
+
Test.load_tests(__FILE__, *ARGV)
|
246
|
+
</pre>
|
247
|
+
|
248
|
+
|
249
|
+
h2. A Complete Sample Project
|
250
|
+
|
251
|
+
p(comment). Not bloody likely.
|
252
|
+
|
253
|
+
</div>
|
data/etc/doc/generate.rb
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
#
|
2
|
+
# = generate.rb, for the ruby-journal project.
|
3
|
+
#
|
4
|
+
# Documents are written in Textile and converted to HTML with RedCloth.
|
5
|
+
#
|
6
|
+
# However, RedCloth only generates HTML _fragments_. We need to generate HTML _documents_,
|
7
|
+
# with <tt><head></tt> information (especially CSS), etc.
|
8
|
+
#
|
9
|
+
# The simple function +generate_document+ does this.
|
10
|
+
#
|
11
|
+
|
12
|
+
require 'rubygems'
|
13
|
+
require 'redcloth'
|
14
|
+
require 'extensions/io'
|
15
|
+
require 'celsoft.com/template'
|
16
|
+
|
17
|
+
#
|
18
|
+
# Takes the Textile file from +path+ (relative to ~/Projects/dev-utils) and generates an HTML
|
19
|
+
# file in the appropriate place, which is the <tt>build/www</tt> directory, and with an +html+
|
20
|
+
# instead of +textile+ extension.
|
21
|
+
#
|
22
|
+
# The HTML document will contain an inline stylesheet.
|
23
|
+
#
|
24
|
+
# The first "h1." tag in the document is used as the title of the HTML page.
|
25
|
+
#
|
26
|
+
# Special lines !header and !toc are expanded.
|
27
|
+
#
|
28
|
+
def generate_document(input_path, output_dir)
|
29
|
+
output_path = File.join(output_dir, "#{File.basename(input_path)}".sub(/\.textile/, ".html"))
|
30
|
+
raw_text = File.read(input_path)
|
31
|
+
#trace {'input_path'}
|
32
|
+
#trace { 'raw_text.length' }
|
33
|
+
input_text = process_text(raw_text)
|
34
|
+
red_cloth_text = RedCloth.new(input_text)
|
35
|
+
red_cloth_text.fold_lines = true
|
36
|
+
html_fragment = red_cloth_text.to_html
|
37
|
+
html = html_wrap(html_fragment)
|
38
|
+
File.write(output_path, html)
|
39
|
+
#File.write(output_path + '.tmp', input_text)
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# Expand any meta-markers like !header and !toc.
|
44
|
+
#
|
45
|
+
def process_text(text)
|
46
|
+
require 'shellwords'
|
47
|
+
text.gsub(/^!(.*)\s*$/) {
|
48
|
+
command, *args = Shellwords.shellwords($1.strip)
|
49
|
+
case command
|
50
|
+
when 'header' then header(*args)
|
51
|
+
when 'toc'
|
52
|
+
_toc = toc(text)
|
53
|
+
_toc
|
54
|
+
else
|
55
|
+
raise "Unknown command embedded in textile input: #{command}"
|
56
|
+
end
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
CSS_FILE = 'etc/doc/textile.css'
|
61
|
+
|
62
|
+
#
|
63
|
+
# Wraps the given HTML fragment in head, body, etc., to produce a proper document.
|
64
|
+
#
|
65
|
+
# It points to a hardcoded stylesheet.
|
66
|
+
#
|
67
|
+
def html_wrap(fragment)
|
68
|
+
require 'extensions/string'
|
69
|
+
title = fragment.scan(%r{<h1>(.*?)</h1>}).first || []
|
70
|
+
title = title.first || "(no title)"
|
71
|
+
return %{
|
72
|
+
<html>
|
73
|
+
<head>
|
74
|
+
<title>#{title}</title>
|
75
|
+
<style type="text/css">
|
76
|
+
#{File.read(CSS_FILE).tabto(6)}
|
77
|
+
</style>
|
78
|
+
</head>
|
79
|
+
<body>
|
80
|
+
#{fragment}
|
81
|
+
</body>
|
82
|
+
</html>
|
83
|
+
}.tabto(0)
|
84
|
+
end
|
85
|
+
|
86
|
+
def header(*args)
|
87
|
+
require_arg = args.shift or raise ArgumentError
|
88
|
+
require_text = "%(small-title)<code>require '#{require_arg}'</code>%"
|
89
|
+
if args.shift == 'main'
|
90
|
+
main_page_link = '%(mylink)"main page":index.html%'
|
91
|
+
else
|
92
|
+
main_page_link = ''
|
93
|
+
end
|
94
|
+
%!table{width:100%}.\n| #{require_text} |>. #{main_page_link} |\n\n!
|
95
|
+
end
|
96
|
+
|
97
|
+
TOC_TEMPLATE = Template::Document.new
|
98
|
+
TOC_TEMPLATE.load %!
|
99
|
+
<table class="toc_table">
|
100
|
+
<tr>
|
101
|
+
<td>
|
102
|
+
<span class="header">Links</span><br/>
|
103
|
+
<ul id="links">
|
104
|
+
${each links}
|
105
|
+
<li><a href="${var href}">${var name}</a></li>
|
106
|
+
${end}
|
107
|
+
</ul>
|
108
|
+
</td>
|
109
|
+
<td>
|
110
|
+
<span class="header">Contents</span><br/>
|
111
|
+
<ul id="contents">
|
112
|
+
${each contents}
|
113
|
+
<li><a href="#\${var anchor}">${var heading}</a>
|
114
|
+
${if subheadings}
|
115
|
+
<ul>
|
116
|
+
${each subheadings}
|
117
|
+
<li><a href="#\${var anchor}">${var heading}</a></li>
|
118
|
+
${end}
|
119
|
+
</ul>
|
120
|
+
</li>
|
121
|
+
${end}
|
122
|
+
${end}
|
123
|
+
</ul>
|
124
|
+
</td>
|
125
|
+
</tr>
|
126
|
+
</table>
|
127
|
+
!
|
128
|
+
|
129
|
+
Heading = Struct.new(:level, :heading, :anchor)
|
130
|
+
|
131
|
+
# Returns the HTML for a table containing links (from links.dat) and the contents
|
132
|
+
# of this page, derived from the given text. h2 and h3 markup elements are taken
|
133
|
+
# to be first- and second-level headings in the text. The text itself is modified
|
134
|
+
# so that those headings have anchors on them.
|
135
|
+
def toc(text)
|
136
|
+
# Form links: [ { 'name' => 'Synopsis', 'href' => 'Synopsis.html' }, ... ]
|
137
|
+
links = links().map { |name, href|
|
138
|
+
Hash[ 'name', name, 'href', href ]
|
139
|
+
}
|
140
|
+
|
141
|
+
# Form contents: [
|
142
|
+
# { 'heading' => 'Introduction', 'anchor' => 'Introduction', 'subheadings' => [ { ... } ] },
|
143
|
+
# ...
|
144
|
+
# ]
|
145
|
+
regex = /^h([234])\.\s+(.*?)$/
|
146
|
+
headings = text.grep(regex).map { |line|
|
147
|
+
line =~ regex
|
148
|
+
level, heading = $1.to_i - 1, $2.strip
|
149
|
+
anchor = heading.gsub(/[^\s\w]/, '')
|
150
|
+
#Hash[ 'level', level, 'heading', heading, 'anchor', anchor ]
|
151
|
+
Heading.new(level, heading, anchor)
|
152
|
+
}
|
153
|
+
contents = []
|
154
|
+
headings.each do |h|
|
155
|
+
case h.level
|
156
|
+
when 1
|
157
|
+
contents << Hash['heading', h.heading, 'anchor', h.anchor]
|
158
|
+
when 2
|
159
|
+
(contents.last['subheadings'] ||= []) << Hash['heading', h.heading, 'anchor', h.anchor]
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
# Place anchors into document. This changes the input text.
|
164
|
+
text.gsub!(regex) {
|
165
|
+
match = Regexp.last_match
|
166
|
+
heading = $2.strip
|
167
|
+
anchor = heading.gsub(/[^\s\w]/, '')
|
168
|
+
match[0].chomp + %{ <a name="#{anchor}"/>\n}
|
169
|
+
}
|
170
|
+
|
171
|
+
# Run it through the template.
|
172
|
+
TOC_TEMPLATE.data = { 'links' => links, 'contents' => contents }
|
173
|
+
TOC_TEMPLATE.output
|
174
|
+
end
|
175
|
+
|
176
|
+
# Return [ [name, href], [name, href], ... ].
|
177
|
+
def links
|
178
|
+
@links ||=
|
179
|
+
begin
|
180
|
+
links_file = Pathname.new(__FILE__).dirname + 'links.dat'
|
181
|
+
File.readlines(links_file).grep(/^\w/).map { |line|
|
182
|
+
line =~ %r{^(.*?)/(.*)$} or raise "Bad data in links.dat."
|
183
|
+
[$1.strip, $2.strip]
|
184
|
+
}
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
@@ -0,0 +1,110 @@
|
|
1
|
+
!header dev-utils nomain
|
2
|
+
|
3
|
+
h1. The Ruby dev-utils Project
|
4
|
+
|
5
|
+
!toc
|
6
|
+
|
7
|
+
h2. About dev-utils
|
8
|
+
|
9
|
+
p. @dev-utils@ provides utilites to assist the process of developing Ruby
|
10
|
+
programs. At the moment, the target areas are debugging and unit testing
|
11
|
+
(planned).
|
12
|
+
|
13
|
+
Version 1.0 was released on 2004-10-08 as a RubyGem. RPA and tarball
|
14
|
+
installation will be provided shortly in 1.0.1. Throughout this
|
15
|
+
documentation, there are references to planned features. These will be
|
16
|
+
released in 2.0, for which there is no estimated completion date.
|
17
|
+
|
18
|
+
h3. Debugging
|
19
|
+
|
20
|
+
With @dev-utils/debug@ you can:
|
21
|
+
|
22
|
+
* Escape to an IRB session from a running program.
|
23
|
+
|
24
|
+
<pre style="margin-left:5em">
|
25
|
+
breakpoint
|
26
|
+
breakpoint 'Person#name' # Identify it when it happens.
|
27
|
+
breakpoint { @name } # Default return value.
|
28
|
+
</pre>
|
29
|
+
|
30
|
+
* Access a no-config logfile for debugging.
|
31
|
+
|
32
|
+
<pre style="margin-left:5em">
|
33
|
+
debug 'Database connection established' # Look in ./debug.log
|
34
|
+
</pre>
|
35
|
+
|
36
|
+
* Trace expressions in that logfile.
|
37
|
+
|
38
|
+
<pre style="margin-left:5em">
|
39
|
+
trace 'x + y'
|
40
|
+
trace 'Process.pid'
|
41
|
+
trace 'names', :pp # Pretty-print.
|
42
|
+
trace 'page_structure', :yaml # YAML representation.
|
43
|
+
</pre>
|
44
|
+
|
45
|
+
* %(planned)Find the difference between complex objects (planned).%
|
46
|
+
|
47
|
+
For more information, see "Debugging Aids":DebuggingAids.html.
|
48
|
+
|
49
|
+
<div class="planned">
|
50
|
+
|
51
|
+
h3. Unit Testing (Planned)
|
52
|
+
|
53
|
+
With @dev-utils/test@ you can:
|
54
|
+
* Run some or all of your unit tests, automatically finding the library code.
|
55
|
+
* Load test data from a separate data directory.
|
56
|
+
|
57
|
+
For more information, see "Unit Test Organisation":UnitTestOrganisation.html.
|
58
|
+
|
59
|
+
</div>
|
60
|
+
|
61
|
+
|
62
|
+
h2. Internet Links
|
63
|
+
|
64
|
+
|{width:25ex}. Home page: | "http://dev-utils.rubyforge.org":home |
|
65
|
+
| Project page: | "http://rubyforge.org/projects/dev-utils":project |
|
66
|
+
| Download: | "http://rubyforge.org/frs/?group_id=270":download |
|
67
|
+
| API Documentation: | "http://dev-utils.rubyforge.org/api":api |
|
68
|
+
|
69
|
+
[home]http://dev-utils.rubyforge.org
|
70
|
+
[project]http://rubyforge.org/projects/dev-utils
|
71
|
+
[download]http://rubyforge.org/frs/?group_id=270
|
72
|
+
[api]http://dev-utils.rubyforge.org/api
|
73
|
+
|
74
|
+
|
75
|
+
h2. Administrivia
|
76
|
+
|
77
|
+
h3. Credits
|
78
|
+
|
79
|
+
The breakpoint-related code was contributed unwittingly by Joel VanderWerf and
|
80
|
+
Florian Gross. The rest of the code is by Gavin Sinclair.
|
81
|
+
|
82
|
+
h3. Notes
|
83
|
+
|
84
|
+
p. @dev-utils@ depends on "@extensions@":http://extensions.rubyforge.org, version
|
85
|
+
0.5 or greater.
|
86
|
+
|
87
|
+
Runnable examples are located in the @examples@ directory of the distribution.
|
88
|
+
|
89
|
+
h3. License
|
90
|
+
|
91
|
+
Copyright (c) 2004, Gavin Sinclair.
|
92
|
+
|
93
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
94
|
+
of this software and associated documentation files (the "Software"), to deal
|
95
|
+
in the Software without restriction, including without limitation the rights
|
96
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
97
|
+
copies of the Software, and to permit persons to whom the Software is
|
98
|
+
furnished to do so, subject to the following conditions:
|
99
|
+
|
100
|
+
The above copyright notice and this permission notice shall be included in all
|
101
|
+
copies or substantial portions of the Software.
|
102
|
+
|
103
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
104
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
105
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
106
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
107
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
108
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
109
|
+
SOFTWARE.
|
110
|
+
|