Automated unit testing in classic ASP? Some might think now that this is not possible. But ajaxed allows us to create tests for our asp application. Check the overview of the built-in unit testing module:
- Offers unit testing like you might know it from junit, nunit, etc. Including all the known assertions.
- Test runner within the ajaxed console or directly executable
- Additionally it offers functionality tests to check and ensure that all your pages are responding correctly.
Writing your first test
<!--#include virtual="/ajaxed/class_TestFixture/testFixture.asp"-->
<%
set tf = new TestFixture
tf.allEnvs = true
tf.run()
sub test_1()
tf.assert 1 = 1, "1 is not equal 1"
end sub
%>
Run this code — test_first.asp
You should see a test report when running that file. It shows if anything is working smoothly or if there are any errors. The code above results in no failures. Check the following - which contains an obvious failure (1 is not equal to 2):
<!--#include virtual="/ajaxed/class_TestFixture/testFixture.asp"-->
<%
set tf = new TestFixture
tf.allEnvs = true
tf.run()
sub test_1()
tf.assert 1 = 2, "1 is not equal 1"
end sub
%>
Run this code — test_fail.asp
Ok, now lets explain the code:) Normally every page in your app would contain an instance of
AjaxedPage
. The only exception is a test file because it contains an instance of
TestFixture
. For this reason the first line loads (includes) the
TestFixture
class and an instance named
tf
is created on the following line. Last but not least it is required to run the test with the
run()
method.
Note: By default all tests are only runnable on the DEV environment (security). To enable a test on all environments it's required to set the allEnvs
to true
. All examples here will contain that setting.
How to structure a test fixture?
The
TestFixture
class comes with a lot of assertion methods which are only executeable within a test method. So we need to create a test method first. A test method has the following signature:
Test methods: a sub prefixed with test_
and followed by a continous number (starting with 1)
<%
sub test_1()
'your asserts
end sub
sub test_2()
'other asserts
end sub
'IMPORTANT: This test won't be called cause
'the test_3 is missing. Tests are not in
'continous order
sub test_4()
end sub
%>
Setup method
Sometimes you want to perform certain tasks before running each of your test methods (e.g. opening a database connection, etc.). In that case we just add a
setup()
procedure into our test and it will be executed automatically before each test method.
Naming the test file
The naming of the test file is up to you. However, it is recommended to prefix it with
test_
. Prefixing allows you to identify your tests much quicker and additionally they will be available within your ajaxed console (under the "Test" tab).
Assertion examples
The following example outlines only the most important assertions you should know. In order to get an overview of all please refer to the
latest API.
Most important to remember when working with assertions is that the last parameter always contains a message which will be displayed if the assertion fails.
<!--#include virtual="/ajaxed/class_TestFixture/testFixture.asp"-->
<%
set tf = new TestFixture
tf.allEnvs = true
tf.run()
sub test_1()
with tf
'simple
.assert true, "Asserts truth"
.assertEqual true, true, "Asserts equality"
.assertNotEqual 1, 2, "Asserts not equality"
.assertInDelta 10, 15, 5, "Number with tolerance (delta)"
.assertInstanceOf "TestFixture", tf, "Asserts a type"
.assertNothing nothing, "Asserts that an object is nothing"
'advanced
.assertMatch "\d+", "12312", "Asserts to a given regex pattern"
.assertInFile "/ajaxed/ajaxed.asp", "include", "Asserts a string in a file"
.assertEqual array("x", "y"), array("x", "y"), "Asserts equality also on arrays"
'contains assertions
.assertHas array(1, 2, 3), 2, "Asserts containment"
.assertHasNot array(1, 2, 3), 5, "Asserts non existence"
end with
end sub
%>
Run this code — test_assertions.asp
Force failure
Sometimes you need to perform a customized test which requires more than a simple assertion. Still you want to place that test into your test fixture because this is where it should be. To perform such tests you will require to fail a test manually. Thats possible with the
fail()
method.
<!--#include virtual="/ajaxed/class_TestFixture/testFixture.asp"-->
<%
set tf = new TestFixture
tf.allEnvs = true
tf.run()
sub test_1()
if lib.env = "LIVE" then
tf.fail "i want the test to fail"
end if
end sub
%>
Run this code — test_manually_fail.asp
Real world example
There are many different opinions out there on how many tests you should write. I am sure you have your own as well and that's why we kill that discussion here.
Nevertheless there is one thing which I strongly recommend when working with classic ASP: Testing the availability of each of your asp files. The test is setup quickly (does not hurt) and gives you an overview if all your pages are working properly (do not throw an unexpected error).
Our friend is the assertion
assertResponse()
which lets us check if a page contains a given response text (please refer to the API for a more detailed description). The following script tests some pages of the ajaxed.org page.
<!--#include virtual="/ajaxed/class_TestFixture/testFixture.asp"-->
<%
set tf = new TestFixture
tf.allEnvs = true
tf.run()
'testing our most important pages
sub test_1()
with tf
.assertResponse "/api/", empty, "API", "API has a problem"
.assertResponse "/", empty, "ajaxed", "Main page has a problem"
.assertResponse "/about/", empty, "michal", "About page has a problem"
.assertResponse "/download/", empty, "2.0", "Download page is not workin"
end with
end sub
%>
Run this code — test_response.asp
Tip: We strongly recommend creating a test for your asp files. That saves you the time to browse each page manually.