News |
SUnit Update |
The SUnit project is moving again with 3 new releases in the last year. Project releases are now placed in the public repositories for the relevant dialects (i.e. the Cincom Open Repository, the VastGoodies site, etc.) wherever these exist, being stored here only where the dialect lacks a sufficiently well-known one.
SUnit 4.0, 3.3 and 3.2 changes from 3.1 |
SUnit 4.0
TestResult now double-dispatches via the exception (see #sunitAnnounce:toResult:). This makes it easier for users to plugin specific behaviour.
TestResource #setUp and #tearDown is now consistent with TestCase #setUp and #tearDown. TestResource>>setUp is _not_ called by TestResource>>initialize; the framework calls TestResource>>setUp separately. If TestResource>>setUp is entered then a call of TestResource>>tearDown is ensured, just as for TestCase. (TestResource>>uninitialize, introduced in in SUnit 3.2 in an earlier attempt to address this problem, is now deleted.)
IMPORTANT: it has always been the case that TestCase>>tearDown code may require
someVar isNil or: [someVar doTearDownStuff].guards to handle the possibility that the test fails in early #setUp before someVar has been assigned (the symptom of not having the guard is that the run shows two errors for the same test in that case). The above change to TestResult means that some resource #tearDown code may now also require these guards. These cases are usually very obvious to spot and fix, so we have accepted this side effect of the change.
Otherwise, framework behaviour and API are unaffected by this change. However in the very rare case that a user has written a programmatic script for manipulating TestResources, they would need to replace any
var := MyTestResource new.
with
var := MyTestResource new; setUp.
since #new's call of #initialize no longer calls #setUp.
There are changes to #testSelectors, #allTestSelectors, #sunitAllSelectors (which is now deprecated) and #sunitSelectors (which is now in protocol 'private', does not guarantee order, is now trivial to inline and may in future be deprecated). Associated changes to #buildSuiteFromSelectors, with deletion of #buildSuiteFromLocal/AllSelectors, integrate suite building with #shouldInheritSelectors and a new method, #lookupHierarchyRoot, giving more consistent test inheritance behaviour, and better performance in hierarchies with many selectors and fewer test selectors. Any utilities that called #buildSuiteFromLocal/AllSelectors explicitly can eliminate both calls, and the boolean test that decides which call to send, in favour just calling #buildSuiteFromSelectors.
In all normal-usage cases, TestResources now ask their requesting test or candidate-resource to signal their failure, thus providing more informative logging.
SUnit 3.3
It introduced the method TestResource class>>resetResources: to ensure safe ordering of resource tearDown in edge cases where multiple resources used by a suite could share dependency on a resource.
SUnit 3.2
It made the order of TestResource tearDown be the reverse of the order of TestResource setUp. It made resource setUp lazy: the first test in a suite that requires a given resource attempts to set it up and the result of the attempt applies throughout that run of the suite. Thus tests that do not require a failed-setUp resource still run, rather than the whole suite aborting.
It introduced TestAsserter, a common superclass of TestResource and TestCase that assists refactoring of code from one to the other (and also provides a suitable superclass for any TestCase delegate classes users may create).
It made minor method category changes for consistency.
SUnit 3.1 changes from earlier versions |
What's new in SUnit 3.1
SUnit 3.1 includes a various bug fixes, as well as a small number of additions and extensions to SUnit. The reason for the release's delay has been the lack of time available to devote to the project, and the problems associated with creating a clean, dialect-independent code base.
SUnit Camp Smalltalk is still available in four parts:- SUnitPreload
- SUnit
- SUnitTests
- SUnitUI
This is a list of the changes made to each module.
SUnitPreload
- the class ResumableTestFailure has been added
- the dialect-specific Error exception has been factored out from TestResult class>>#exError to SUnitNameResolver class>>#errorObject, removing the last dailect dependency from the SUnit core.
- the dialect-specific MessageNotUnderstood exception is available as SUnitNameResolver class>>#mnuExceptionObject
- the dialect-specific Notification exception is available as SUnitNameResolver class>>#notificattionObject
- the dialect-specific default logging device is available as SUnitNameResolver class>>#defaultLogDevice
SUnit Core
The SUnit core package has achieved the goal of having the exact same code for all dialects - almost. The only dialect using a variant code base is Object Studio. Other than that, the changes consist of additions and bug fixes.
Additions
1. Assertion description strings
The TestCase assertion protocol has been extended with a number of methods allowing the assertion to have a description.. These methods take a String as second argument. If the test case fails, this string will be passed along to the exception handler, allowing more variety in messages than "Assertion failed" gives you. Of course, this string can be constructed dynamically.
| e | e := 42. self assert: e = 23 description: 'expected 23, got ' e printString
The added methods in TestCase are:
- #assert:description:
- #deny:description:
- #should:description:
- #shouldnt:description:
2. Logging support
The description strings described above may also be logged to a Stream such as the Transcript, a file, stdout etc. You can choose whether to log by overriding TestCase>>#isLogging in your test case class, and choose where to log to by overriding TestCase>>#failureLog.
3. ResumableTestFailure
A resumable TestFailure has been added. What can this be used for? Take a look at this example:
aCollection do: [ :each | self assert: each isFoo]
In this case, as soon as the first element of the collection isn't Foo, the test stops. In most cases, however, we would like to continue, and see both how many elements and which elements aren't Foo. It would also be nice to log this information. You can do this in this way:
aCollection do: [ :each | self assert: each isFoo description: each printString, 'is not Foo' resumable: true]
This will print out a message to your logging device for each element that fails. It doesn't cumulate failures, i.e., if the assertion fail 10 times in your test method, you'll still only see one failure.
Bug fixes
- Steve Waring found out that when a test that uses TestResources fails and is debugged, the debug process occurs in a separate thread, and the resources are reset in the normal SUnit thread, before the test method can be analysed. The bug was in TestCase>>#debugAsFailure and has been fixed.
- John Brant found that SUnit handles errors that it shouldn't. The bug was in TestCase>>#executeShould:inScopeOf: and has been fixed.
- Alan Knight found that TestCase>>#setUp should be moved inside the #ensure: block, so that #tearDown is also called in the event of an error during test set-up.
- Reinout Heeck pointed out that the default behavior of TestResource class>>#isAvailable should not only check if the resource is not nil, but should also send the resource itself #isAvailable. This has been corrected.
SUnitTests
- the 2 test methods SUnitTest>>#testDebugUI and SUnitTest>>#testFailureDebugUI have been removed.
- Tests for exception handling have been added
- a TestResource test case has been added
- a ResumableTestFailure test case has been added
SUnitUI
- depending on the dialect, there have been minor changes to the TestRunner.
- The TestRunner title bar now shows the version number declared in TestCase class>>#sunitVersion. This eliminates the need to change this package for every new release of the core package.
- Many versions of TestRunner have had a dependency on the SUnitTests package. This dependency has been removed.
- Many versions of TestRunner have presumed that the test failures are an OrderedCollection. This has been corrected.
- The method "TestRunner open" is now standard for opening the TestRunner.