|
Auto-tester
From Iteration 1 upto your final presentation, we will always test your program by an automated
tester called Autotester. The
Auto-tester is implemented in C++ and comes in the form of a static library that
will be linked with your SPA source to make a separate application. In order to
run the Auto-tester, ensure that you have installed Visual Studio 2010. Further instructions are given below.
Preparing for Auto-testing
You need to enable the Auto-tester to talk to your SPA program. The steps to do that:
- Download the zip file
containing all the necessary Autotester files. It has these files:
- AutoTesterInUse.sln, AutoTesterInUse.suo, AutoTesterInUse.ncb, AutoTesterInUse.vcproj, Release/AutoTesterInUse.res
Visual Studio.Net 2008 related files. Simply click on the sln file to open
the solution in your Visual Studio IDE. - AutoTesterLib.lib
This is a static library containing the
object (.obj) files that will be subsequently
linked with the object files of your SPA.
This one works under the "Release" mode, when you build your solution.
- AutoTesterLib_debug.lib
This is a static library containing the object (.obj) files that will be
subsequently linked with the object files of your SPA. This one works under the
"Debug" mode, when you build your solution.
- AbstractWrapper.h
This is a header file that must be placed in the
same directory as TestWrapper.h. Please do NOT
modify this file (otherwise, it will cause problems
for the AutoTester later).
- TestWrapper.h
This is a header file containing the
specification of a TestWrapper class that
is in charge of the communication between
the Auto-tester and your SPA.
- TestWrapper.cpp
This file will contain the implementation of
the various methods of the TestWrapper class.
The implementation of these methods will be
done by you. Comments are included in the file
to guide you.
- Release/trial.txt
A sample source program (in SIMPLE) for you
to test your TestWrapper implementation.
- Release/trialcase.txt
A set of queries to go with the sample source
program. Note that this is just a sample set
of queries. The source program and queries
used in the final testing will be more
complicated than this !
Also note that this set of test queries may include queries that you
have not implemented yet.
Please modify accordingly. The first line of this file contains the
total number of queries in the file. Use 'cat : <category>' to
categorize your test cases (<category> will be displayed in the result). Rest of the file specify test
cases - five line for each case: test case id, declaration, query,
expected result, and allowed time in milliseconds. - Release/trialcase_NEW.txt
The same queries as those in 'trialcase.txt'. This test case file contains the
category tags and comments for each query inside.
- Release/analysis.xsl
After full run of test cases, the auto-tester will generate an xml file
(out.xml). Open this xml file in Internet Explorer. IE will
automatically convert the xml file to an html file using analysis.xsl.
- To hook up to the Auto-tester, you only need to implement
the TestWrapper class. The following is the source of
TestWrapper.h:
#ifndef TESTWRAPPER_H
#define TESTWRAPPER_H
#include <string>
#include <iostream>
#include <list>
#include "AbstractWrapper.h"
// include your other headers here
class TestWrapper : public AbstractWrapper {
public:
// a default constructor
TestWrapper();
// method for parsing the SIMPLE source
virtual void parse(std::string filename);
// method for evaluating a query
virtual void evaluate(std::string query, std::list<std::string>& results);
};
#endif
First, in the header file (TestWrapper.h), include any other
header files necessary for compiling the TestWrapper class.
If you need to use instance variables in your implementation,
create a private section in the class specification and declare
your instance variables there. Next, you need to implement the
3 methods specified in TestWrapper.h by writing code for the
methods in TestWrapper.cpp.
The first method is the default constructor. In this method,
you can create objects that you will need later on for
parsing and query evaluation. You can also do any
initialization your need for your SPA here.
The second method is called parse. The Auto-tester will pass
the name of the SIMPLE source file through parameter
"filename" of this method. What you need to do here is to
write code that will invoke the parser/design extractor
of your SPA to create the PKB components from the source file.
The third method is called evaluate. It has 2 parameters:
query will contain the query string while results will
store the answers to the query. Here, you will write
code that will invoke your SPA to evaluate the query.
The answers to the query will be subsequently stored in the
results list.
The PQL query comes in the form of a single line (Even though it is given as
two lines in the test case file - those two lines are concatenated by the
Auto-tester with a space in the middle). For
example, "assign a; stmt s; Select <a, s> such that Parent(s, a)". There's only a space between the declarations
and the query (not a newline). On the other hand, answers
to the query must be stored as std::strings in the results list.
For example, if the answer to the query is 1 2, 1 5 and 1 8,
results will contain 3 elements: "1 2", "1 5" and "1 8".
We shall now discuss the different formats of the returned results:
- Select BOOLEAN ......
For boolean results, the results list contains
only one element - "true" or "false", with all characters
in lowercase.
- Select a such that ....
For example, if your answer is 9, 7, 1 and 3,
then the results list will contain 4 string elements:
"9", "7", "1" and "3". Note that you only need to return the
statement number(s) if the synonym in the Select clause
is of type statement, assign, while or if. If the synonym
is of type variable or procedure, return the variable and
procedure names respectively.
- Select <p, s> such that ...
For tuple results, each result is stored as a string
in the results list. However, each component of a
result must be separated by one space.
For example, if the results are <p, 1>, <q, 4>,
then the results list will contain 2 elements: "p 1"
and "q 4". Notice that there is only one space between p
and 1 as well as q and 4 (two or more spaces are not allowed).
- Select s.stmt#... or Select <p.procName, v.varName>...
The format of the results is similar to the previous
two cases. For example, if the results to "Select s.stmt#..."
are 1 and 6, the results list will contain 2 elements:
"1" and "6".
- If there are no results, just leave the
results list empty. Don't add anything to the results
list, not even an empty string.
Important: The order of the results is not
important. The Auto-tester will do the sorting of the results
for you. The Auto-tester will also remove any duplicates it
finds in the answers. For example, if you return the answers
"1", "3", "3", "2", "3", the Auto-tester will consider your
answers to be just "1", "2" and "3".
Note also that when the result is a procedure name or
variable name, make sure you do not change the case. For
example, if the result is procedure First, it should be returned
as "First", not "first" or "FIRST" or "FiRSt" etc.
- The Auto-tester works in a cooperative mode. In other
words, instead of forcing your program to stop whenever the
time limit is reached during the evaluation of a query, it
will first signal to your program to stop. Then, it waits for
a couple of seconds for your program to do any clean up
e.g. deallocating memory etc. If your program returns within
the extended time limit, the Auto-tester will continue with the
next query. Otherwise, it will print out a message to inform
us that the program has refused to terminate, in which case
we will forcefully terminate the whole testing and give a full
penalty for that query.
It is important that you return the goodwill of the Auto-tester by
responding to the stop signal. We will heavily penalize programs that refuse to cooperate with the Auto-tester. To do
the checking of the stop signal, you need to add some code into
your own SPA program as sketched out in the following pseudocode:
#include "AbstractWrapper.h"
.....
for each query_clause in query do
evaluator.eval(query_clause)
if (AbstractWrapper::GlobalStop) {
// do cleanup
....
return
}
.....
First, ensure that you add the AbstractWrapper header file Thread.h using '#include
"AbstractWrapper.h"'. To check for the stop signal, you check the static
global variable AbstractWrapper::GlobalStop which is a bool value. If the value is true, it means that the time has
expired for the query and you should stop execution and do any
cleanup and return control back to the Auto-tester. Otherwise,
you are still within the time limit and you can continue processing
the query.
You can do the checking at more than one place in your program. For example,
the evaluation of Affects* is often time consuming. So, you might want to do
a check for every 50 answers found during the evaluation of an Affects*.
Since every team's implementation is different, you have to judge for
yourself where are good points in your program to do this checking. Generally, you will want to do
checking in strategic places e.g. after the evaluation of a query
clause. However, note that checking takes time. Therefore, too much checking
may slow down your system. There is no hard and fast rule on how much checking
is required. You have to find a suitable
level that will strike a balance between the efficiency and cooperativeness
of your implementation.
Compiling and running the Auto-tester
Once you have implemented your TestWrapper class and added the necessary
checking code in your SPA program, it is time to compile the Auto-tester
with your SPA program. Simply use Visual Studio automatic build tool (press F7).
Important: The `main' method is located in
the Auto-tester. Therefore, you should not compile a source
file that contains the method main. Either remove it or
comment it out.
To run the Auto-tester, enter the following command from the command prompt at
the release directory:
AutoTester trial.txt trialcase.txt out.xml
The Auto-tester accepts three arguments. The first is the name of the file
containing the SIMPLE source. The second is the name of the file containing the
queries. The third is the output file to store the results of the testing.
Alternatively you can set the property of AutoTesterInUse.sln by clicking
Project > AutoTesterInUse Properties > Debugging > Command Arguments from the
menu bar of VS.Net and provide: Release\trial.txt Release\trialcase.txt
Release\out.xml ,as arguments. After setting this, you can simply press Ctrl+F5
(Run without debugging) to kick-start that auto-testing process.Once the testing
is completed, you can view the results of the testing by opening out.xml in
Internet Explorer (IE); IE will be using analysis.xsl to convert out.xml to an
HTML document.
Important points
On the day of your final presentation, make sure your SPA can
communicate with the Auto-tester as described above. The Auto-testing
procedure on that day will be similar except that we will be feeding the Auto-tester
with our own set of source program and test queries.
There are some important points you need to take note of:
- The Auto-tester program make use of the namespace AutoTester.
Therefore, if you are using namespace in your program, you
should avoid calling your namespace AutoTester.
- Please follow the answer format strictly. For example,
if you're returning tuple results such as "1 2", "3 4" etc,
make sure that you don't have excessive spaces in-between.
Answers such as "1 2"
will be regarded as wrong by the Auto-tester. This will in
turn result in unnecessary time waste when we double-check
the failed cases.
- During the implementation of your TestWrapper, you might want
to print some debugging information to the standard output.
This is allowed but please remove/comment out those std::cout statements
before you go for the final testing. Printing debugging information during
the testing will slow down your SPA and result in unnecessary timeouts (each
query is only allowed a certain amount of time to complete)
- Please compile your program in Release configuration. By default, AutoTesterInUse solution uses Release
configuration. Mostly due to inappropriate coding practice, one might find
problem/bugs when switching between Debug and Release configuration. Release
configuration performs optimization, while Debug doesn't. For a list of
advice on this issue see:
- The SIMPLE source file used for the final testing will be around
300 to 400 lines. The number of test queries are also around
300-400. So, do be prepared for an extensive final testing.
You should also try to run your own SPA for a large set of
consecutive queries say 100-200 queries on a specific SIMPLE
source file to see whether your SPA is robust enough to withstand
large number of queries without exiting
- Auto-tester is not 'open-source'. Please do not request for the source
code for Auto-tester.
- You are welcome to use Auto-tester for your own system testing. But the
main purpose of Auto-tester is final testing, for which it has been proved
to be adequate. Therefore, no requests for enhancements please.
|