Here are just a few thoughts on what I learned writing ACPG unit tests.
My perception is that I spent a lot of time spinning wheels at first.
However, following these rules as I learned them increased the speed of
writing tests by an order of magnitude.
If you think it worthwile I could go over this in less than two minutes
at a morning meeting.
Lessons Learned In ACPG Regression Testing
Note: "Target" refers to the code being tested. Test classes test the
target code.
(1) When testing Oracle packages create one test class per target Oracle
package; when testing .NET code create one test class per target .NET
class.
(2) Use the Nunit or MbUnit feature which runs all regressions
sequentially with a single click.
(3) Avoid elaborate test setups in which the test classes duplicate the
insertion and creation target objects in the module being tested.
Elaborate test setups can take as long to write as the target code being
tested due to the fact that the setup has to do the same thing as the
targetcode.
Whenever possible use the target objects' own procedures to setup test
data for test objects. This means finding out the order in which data is
entered and deleted. First create test objects for target procedures
that create or insert data. Then create test objects for target
procedures that display, delete or archive data.
(4) If test classes create data make sure that they use any Oracle
sequences which exist for that purpose.
(5) Although it would be desirable to use VB.NET transactions and
rollback to remove effects of testing this may not be possible. Many
Oracle objects include commits inside their procedures. Thus they cannot
be rolled back.
(6) Do not create special scripts that call the test classes. These are
hard to maintain, as it is easy to forget which script calls which test
classes. Rather, each test class should call whatever other test classes
it needs.
(7) Place connection info at top of each test class rather than
embedding connect strings inside class member functions. Similary, place
reused parameters (e.g., registry_id) as public parameters within each
test class.
(8) When creating VB.Net variables to hold database columns make sure
that the attribute is the same datatype as the database column. If the
attribute needs to be converted to a string for use in a SQL statement
then use the toString() function. Do not convert Integers to strings
when retrieving them.
(9) Give the names of test class attributes a prefix so that the names
don't accidentally get overridden by local variables inside member
functions. To create the names of test classes and test class member
functions prefix the word "test" to the corresponding names of Oracle
packages and procedures.
(10) IMPORTANT: The first thing to do is to create stubs for all test
classes and test class member functions using the naming convention in
(9) and the connection data in (7). Have each member function of each
test class open up and close a connection.
(11) Each test class is its own Nunit or MbUnit
. Each
member function is its own .
(12) MbUnit and Nunit are almost identical so it doesn't matter which is
used. However, GreaterThan in MbUnit is called Greater in Nunit.
(13) Make certain that if an Assertion fails the connection is already
closed. Otherwise as soon as one test class fails all subsequent test
classes fail due to their attempting to open an existing connection.
(14) It doesn't matter much whether test classes are written in VB.NET
or C#. ReSharper and other tools can convert from one to the other. The
functionality is in the .NET objects. Those don't change when changing
.NET languages.
(15) IMPORTANT: In a perfect world each test class could run
independently, so that if one test class throws an assertion that fails
other test classes can still run. In the real world writing test classes
in this manner means that the test classes take as long to write as the
target objects being tested. Rule (3) means that test classes are not
independent.