Since we are testing language processors, each test case has two parts: an input file and an expected output file. For example, in Stage 1/Project 1, a test case may be:
<html>
<MD!myname>Amer</MD>
Hi, my name is <MU!myname>
</html>
with expected output:
<html>
Hi, my name is Amer
</html>
Another possible outputfile which is useful when you want to test just the scanner may be something like:
BegHtml
BegMacroDef (myname)
Text("Amer")
EndMacroDef
Text("Hi, my name is")
MacroUse(myname)
EndHtml
This second output simply has all the tokens in the file. Note that this is not something your project submission needs to do: it is simply a way for you to check the intermediate stage of your project before moving on to the parser.
A key component of testing is to come up with test cases. The test cases must exercise the major paths through your code. For example, you should have tests that use each of the constructs in shtml, including various kinds of blocks (paragraphs, lists, etc.). In addition, you should have test cases that check scope lookup for macros, and maybe even some tests with illegal input just to make sure you are recognizing only correctly formed programs. If your program passes each of these tests then you at least know that your program is likely to be able to handle at least simple programs with each of the constructs. In other words, there are no gaping holes in your program.
Besides coverage tests, your test suite must also contain tests that check the extreme values of the inputs. Programmers often fail to correctly handle the extreme cases. For example, a common error in sort routines is their inability to handle an empty list (which is at one extreme of the spectrum). Let's consider an example for "extreme" inputs for Project 1. For the static scoping, the extreme cases are when a macro being used is declared in the immediately enclosing scope and when a macro declaration is declared in the outermost (<html>...</html>) scope. The above example (with macro myname) is one instance of using a macro in the same scope as its declaration. Here is another example:
<html>
<MD!myname>Amer</MD>
<p>
<MD!myname>John</MD>
<MD!myfullname><MU!myname> Diwan</MD>
<MU!myfullname>
</p>
</html>
In this example, we use a macro within a macro. However, since it is designed to test an extreme situation, the macro myfullname uses another macro, myname, that has a declaration at the same level. Recall from the assignment that the scope of macros begins after the last </MD> in the block. In other words, the above should expand out to:
<html>
<p>
Amer Diwan
</p>
</html>
and NOT
<html>
<p>
John Diwan
</p>
</html>
The mistake is the second case is that the language processor incorrectly started searching for the the macro myname in the current scope (which is normally fine, just not within a macro).
In general, it is very hard to test ones own code, because effectively you are trying to break or find faults in something that you have created. A good idea when generating test cases is to use the specifications to generate the test case rather than your knowledge of the implementation.