root / lib / test / unit.rb @ 16a276fdc77847a92cba21d060b9880eb1fe75bb
View | Annotate | Download (11.6 KB)
| 1 | require 'test/unit/testcase'
|
|---|---|
| 2 | require 'test/unit/autorunner'
|
| 3 | |
| 4 | module Test # :nodoc: |
| 5 | #
|
| 6 | # = Test::Unit - Ruby Unit Testing Framework
|
| 7 | #
|
| 8 | # == Introduction
|
| 9 | #
|
| 10 | # Unit testing is making waves all over the place, largely due to the
|
| 11 | # fact that it is a core practice of XP. While XP is great, unit testing
|
| 12 | # has been around for a long time and has always been a good idea. One
|
| 13 | # of the keys to good unit testing, though, is not just writing tests,
|
| 14 | # but having tests. What's the difference? Well, if you just _write_ a
|
| 15 | # test and throw it away, you have no guarantee that something won't
|
| 16 | # change later which breaks your code. If, on the other hand, you _have_
|
| 17 | # tests (obviously you have to write them first), and run them as often
|
| 18 | # as possible, you slowly build up a wall of things that cannot break
|
| 19 | # without you immediately knowing about it. This is when unit testing
|
| 20 | # hits its peak usefulness.
|
| 21 | #
|
| 22 | # Enter Test::Unit, a framework for unit testing in Ruby, helping you to
|
| 23 | # design, debug and evaluate your code by making it easy to write and
|
| 24 | # have tests for it.
|
| 25 | #
|
| 26 | #
|
| 27 | # == Notes
|
| 28 | #
|
| 29 | # Test::Unit has grown out of and superceded Lapidary.
|
| 30 | #
|
| 31 | #
|
| 32 | # == Feedback
|
| 33 | #
|
| 34 | # I like (and do my best to practice) XP, so I value early releases,
|
| 35 | # user feedback, and clean, simple, expressive code. There is always
|
| 36 | # room for improvement in everything I do, and Test::Unit is no
|
| 37 | # exception. Please, let me know what you think of Test::Unit as it
|
| 38 | # stands, and what you'd like to see expanded/changed/improved/etc. If
|
| 39 | # you find a bug, let me know ASAP; one good way to let me know what the
|
| 40 | # bug is is to submit a new test that catches it :-) Also, I'd love to
|
| 41 | # hear about any successes you have with Test::Unit, and any
|
| 42 | # documentation you might add will be greatly appreciated. My contact
|
| 43 | # info is below.
|
| 44 | #
|
| 45 | #
|
| 46 | # == Contact Information
|
| 47 | #
|
| 48 | # A lot of discussion happens about Ruby in general on the ruby-talk
|
| 49 | # mailing list (http://www.ruby-lang.org/en/ml.html), and you can ask
|
| 50 | # any questions you might have there. I monitor the list, as do many
|
| 51 | # other helpful Rubyists, and you're sure to get a quick answer. Of
|
| 52 | # course, you're also welcome to email me (Nathaniel Talbott) directly
|
| 53 | # at mailto:testunit@talbott.ws, and I'll do my best to help you out.
|
| 54 | #
|
| 55 | #
|
| 56 | # == Credits
|
| 57 | #
|
| 58 | # I'd like to thank...
|
| 59 | #
|
| 60 | # Matz, for a great language!
|
| 61 | #
|
| 62 | # Masaki Suketa, for his work on RubyUnit, which filled a vital need in
|
| 63 | # the Ruby world for a very long time. I'm also grateful for his help in
|
| 64 | # polishing Test::Unit and getting the RubyUnit compatibility layer
|
| 65 | # right. His graciousness in allowing Test::Unit to supercede RubyUnit
|
| 66 | # continues to be a challenge to me to be more willing to defer my own
|
| 67 | # rights.
|
| 68 | #
|
| 69 | # Ken McKinlay, for his interest and work on unit testing, and for his
|
| 70 | # willingness to dialog about it. He was also a great help in pointing
|
| 71 | # out some of the holes in the RubyUnit compatibility layer.
|
| 72 | #
|
| 73 | # Dave Thomas, for the original idea that led to the extremely simple
|
| 74 | # "require 'test/unit'", plus his code to improve it even more by
|
| 75 | # allowing the selection of tests from the command-line. Also, without
|
| 76 | # RDoc, the documentation for Test::Unit would stink a lot more than it
|
| 77 | # does now.
|
| 78 | #
|
| 79 | # Everyone who's helped out with bug reports, feature ideas,
|
| 80 | # encouragement to continue, etc. It's a real privilege to be a part of
|
| 81 | # the Ruby community.
|
| 82 | #
|
| 83 | # The guys at RoleModel Software, for putting up with me repeating, "But
|
| 84 | # this would be so much easier in Ruby!" whenever we're coding in Java.
|
| 85 | #
|
| 86 | # My Creator, for giving me life, and giving it more abundantly.
|
| 87 | #
|
| 88 | #
|
| 89 | # == License
|
| 90 | #
|
| 91 | # Test::Unit is copyright (c) 2000-2003 Nathaniel Talbott. It is free
|
| 92 | # software, and is distributed under the Ruby license. See the COPYING
|
| 93 | # file in the standard Ruby distribution for details.
|
| 94 | #
|
| 95 | #
|
| 96 | # == Warranty
|
| 97 | #
|
| 98 | # This software is provided "as is" and without any express or
|
| 99 | # implied warranties, including, without limitation, the implied
|
| 100 | # warranties of merchantibility and fitness for a particular
|
| 101 | # purpose.
|
| 102 | #
|
| 103 | #
|
| 104 | # == Author
|
| 105 | #
|
| 106 | # Nathaniel Talbott.
|
| 107 | # Copyright (c) 2000-2003, Nathaniel Talbott
|
| 108 | #
|
| 109 | # ----
|
| 110 | #
|
| 111 | # = Usage
|
| 112 | #
|
| 113 | # The general idea behind unit testing is that you write a _test_
|
| 114 | # _method_ that makes certain _assertions_ about your code, working
|
| 115 | # against a _test_ _fixture_. A bunch of these _test_ _methods_ are
|
| 116 | # bundled up into a _test_ _suite_ and can be run any time the
|
| 117 | # developer wants. The results of a run are gathered in a _test_
|
| 118 | # _result_ and displayed to the user through some UI. So, lets break
|
| 119 | # this down and see how Test::Unit provides each of these necessary
|
| 120 | # pieces.
|
| 121 | #
|
| 122 | #
|
| 123 | # == Assertions
|
| 124 | #
|
| 125 | # These are the heart of the framework. Think of an assertion as a
|
| 126 | # statement of expected outcome, i.e. "I assert that x should be equal
|
| 127 | # to y". If, when the assertion is executed, it turns out to be
|
| 128 | # correct, nothing happens, and life is good. If, on the other hand,
|
| 129 | # your assertion turns out to be false, an error is propagated with
|
| 130 | # pertinent information so that you can go back and make your
|
| 131 | # assertion succeed, and, once again, life is good. For an explanation
|
| 132 | # of the current assertions, see Test::Unit::Assertions.
|
| 133 | #
|
| 134 | #
|
| 135 | # == Test Method & Test Fixture
|
| 136 | #
|
| 137 | # Obviously, these assertions have to be called within a context that
|
| 138 | # knows about them and can do something meaningful with their
|
| 139 | # pass/fail value. Also, it's handy to collect a bunch of related
|
| 140 | # tests, each test represented by a method, into a common test class
|
| 141 | # that knows how to run them. The tests will be in a separate class
|
| 142 | # from the code they're testing for a couple of reasons. First of all,
|
| 143 | # it allows your code to stay uncluttered with test code, making it
|
| 144 | # easier to maintain. Second, it allows the tests to be stripped out
|
| 145 | # for deployment, since they're really there for you, the developer,
|
| 146 | # and your users don't need them. Third, and most importantly, it
|
| 147 | # allows you to set up a common test fixture for your tests to run
|
| 148 | # against.
|
| 149 | #
|
| 150 | # What's a test fixture? Well, tests do not live in a vacuum; rather,
|
| 151 | # they're run against the code they are testing. Often, a collection
|
| 152 | # of tests will run against a common set of data, also called a
|
| 153 | # fixture. If they're all bundled into the same test class, they can
|
| 154 | # all share the setting up and tearing down of that data, eliminating
|
| 155 | # unnecessary duplication and making it much easier to add related
|
| 156 | # tests.
|
| 157 | #
|
| 158 | # Test::Unit::TestCase wraps up a collection of test methods together
|
| 159 | # and allows you to easily set up and tear down the same test fixture
|
| 160 | # for each test. This is done by overriding #setup and/or #teardown,
|
| 161 | # which will be called before and after each test method that is
|
| 162 | # run. The TestCase also knows how to collect the results of your
|
| 163 | # assertions into a Test::Unit::TestResult, which can then be reported
|
| 164 | # back to you... but I'm getting ahead of myself. To write a test,
|
| 165 | # follow these steps:
|
| 166 | #
|
| 167 | # * Make sure Test::Unit is in your library path.
|
| 168 | # * require 'test/unit' in your test script.
|
| 169 | # * Create a class that subclasses Test::Unit::TestCase.
|
| 170 | # * Add a method that begins with "test" to your class.
|
| 171 | # * Make assertions in your test method.
|
| 172 | # * Optionally define #setup and/or #teardown to set up and/or tear
|
| 173 | # down your common test fixture.
|
| 174 | # * You can now run your test as you would any other Ruby
|
| 175 | # script... try it and see!
|
| 176 | #
|
| 177 | # A really simple test might look like this (#setup and #teardown are
|
| 178 | # commented out to indicate that they are completely optional):
|
| 179 | #
|
| 180 | # require 'test/unit'
|
| 181 | #
|
| 182 | # class MyTest < Test::Unit::TestCase
|
| 183 | # # def setup
|
| 184 | # # end
|
| 185 | #
|
| 186 | # # def teardown
|
| 187 | # # end
|
| 188 | #
|
| 189 | # def test_fail
|
| 190 | # assert(false, 'Assertion was false.')
|
| 191 | # end
|
| 192 | # end
|
| 193 | #
|
| 194 | #
|
| 195 | # == Test Runners
|
| 196 | #
|
| 197 | # So, now you have this great test class, but you still
|
| 198 | # need a way to run it and view any failures that occur
|
| 199 | # during the run. There are some test runner; console test
|
| 200 | # runner, GTK+ test runner and so on. The console test
|
| 201 | # runner is automatically invoked for you if you require
|
| 202 | # 'test/unit' and simply run the file. To use another
|
| 203 | # runner simply set default test runner ID to
|
| 204 | # Test::Unit::AutoRunner:
|
| 205 | #
|
| 206 | # require 'test/unit'
|
| 207 | # Test::Unit::AutoRunner.default_runner = "gtk2"
|
| 208 | #
|
| 209 | # == Test Suite
|
| 210 | #
|
| 211 | # As more and more unit tests accumulate for a given project, it
|
| 212 | # becomes a real drag running them one at a time, and it also
|
| 213 | # introduces the potential to overlook a failing test because you
|
| 214 | # forget to run it. Suddenly it becomes very handy that the
|
| 215 | # TestRunners can take any object that returns a Test::Unit::TestSuite
|
| 216 | # in response to a suite method. The TestSuite can, in turn, contain
|
| 217 | # other TestSuites or individual tests (typically created by a
|
| 218 | # TestCase). In other words, you can easily wrap up a group of
|
| 219 | # TestCases and TestSuites.
|
| 220 | #
|
| 221 | # Test::Unit does a little bit more for you, by wrapping
|
| 222 | # these up automatically when you require
|
| 223 | # 'test/unit'. What does this mean? It means you could
|
| 224 | # write the above test case like this instead:
|
| 225 | #
|
| 226 | # require 'test/unit'
|
| 227 | # require 'test_myfirsttests'
|
| 228 | # require 'test_moretestsbyme'
|
| 229 | # require 'test_anothersetoftests'
|
| 230 | #
|
| 231 | # Test::Unit is smart enough to find all the test cases existing in
|
| 232 | # the ObjectSpace and wrap them up into a suite for you. It then runs
|
| 233 | # the dynamic suite using the console TestRunner.
|
| 234 | #
|
| 235 | #
|
| 236 | # == Configuration file
|
| 237 | #
|
| 238 | # Test::Unit reads 'test-unit.yml' in the current working
|
| 239 | # directory as Test::Unit's configuration file. It can
|
| 240 | # contain the following configurations:
|
| 241 | #
|
| 242 | # * color scheme definitions
|
| 243 | # * test runner to be used
|
| 244 | # * test runner options
|
| 245 | # * test collector to be used
|
| 246 | #
|
| 247 | # Except color scheme definitions, all of them are
|
| 248 | # specified by command line option.
|
| 249 | #
|
| 250 | # Here are sample color scheme definitions:
|
| 251 | #
|
| 252 | # color_schemes:
|
| 253 | # inverted:
|
| 254 | # success:
|
| 255 | # name: red
|
| 256 | # bold: true
|
| 257 | # failure:
|
| 258 | # name: green
|
| 259 | # bold: true
|
| 260 | # other_scheme:
|
| 261 | # ...
|
| 262 | #
|
| 263 | # Here are the syntax of color scheme definitions:
|
| 264 | #
|
| 265 | # color_schemes:
|
| 266 | # SCHEME_NAME:
|
| 267 | # EVENT_NAME:
|
| 268 | # name: COLOR_NAME
|
| 269 | # intensity: BOOLEAN
|
| 270 | # bold: BOOLEAN
|
| 271 | # italic: BOOLEAN
|
| 272 | # underline: BOOLEAN
|
| 273 | # ...
|
| 274 | # ...
|
| 275 | #
|
| 276 | # SCHEME_NAME:: the name of the color scheme
|
| 277 | # EVENT_NAME:: one of [success, failure, pending,
|
| 278 | # omission, notification, error]
|
| 279 | # COLOR_NAME:: one of [black, red, green, yellow, blue,
|
| 280 | # magenta, cyan, white]
|
| 281 | # BOOLEAN:: true or false
|
| 282 | #
|
| 283 | # You can use the above 'inverted' color scheme with the
|
| 284 | # following configuration:
|
| 285 | #
|
| 286 | # runner: console
|
| 287 | # console_options:
|
| 288 | # color_scheme: inverted
|
| 289 | # color_schemes:
|
| 290 | # inverted:
|
| 291 | # success:
|
| 292 | # name: red
|
| 293 | # bold: true
|
| 294 | # failure:
|
| 295 | # name: green
|
| 296 | # bold: true
|
| 297 | #
|
| 298 | # == Questions?
|
| 299 | #
|
| 300 | # I'd really like to get feedback from all levels of Ruby
|
| 301 | # practitioners about typos, grammatical errors, unclear statements,
|
| 302 | # missing points, etc., in this document (or any other).
|
| 303 | #
|
| 304 | |
| 305 | module Unit |
| 306 | # Set true when Test::Unit has run. If set to true Test::Unit
|
| 307 | # will not automatically run at exit.
|
| 308 | def self.run=(flag) |
| 309 | @run = flag
|
| 310 | end
|
| 311 | |
| 312 | # Already tests have run?
|
| 313 | def self.run? |
| 314 | @run ||= false |
| 315 | end
|
| 316 | end
|
| 317 | end
|
| 318 | |
| 319 | at_exit do
|
| 320 | unless $! || Test::Unit.run? |
| 321 | exit Test::Unit::AutoRunner.run |
| 322 | end
|
| 323 | end
|