Refactoring test suite

This commit is contained in:
2019-01-06 14:26:12 -05:00
parent 2398ba552f
commit c63a0887a3
20 changed files with 70 additions and 81 deletions

5
.gitignore vendored
View File

@@ -1,2 +1,3 @@
*.hanktest
examples/shave/
examples/shave/
transcript.hlog
validating.hlog

View File

@@ -3,5 +3,6 @@ IN DEBUG MODE!
* Framing Hooper...
* In with Hooper...
>>> 2
Harris opens the door and pushes me inside. "Captain," he calls. "Could I have a moment?"
The Captain, looking puzzled, steps out. The door is closed. Hooper stares at me, open—mouthed, about to say something. I probably have less than a minute before the Captain storms back in and declares this plan to be bunkum.

View File

@@ -10,6 +10,7 @@ I am not a machine, whatever they say about me.
>>> 0
They suspect me to be a traitor. They think I stole the component from the calculating machine. They will be searching my bunk and cases.
When they don't find it, they'll come back and demand I talk.
I rattle my fingers on the field table.
* Plan
* Wait

View File

@@ -433,16 +433,16 @@ class Story {
if (linesArray.length > 1) {
// debugTrace('Parsing haxe block "${preprocessedLines}"');
}
var program = parser.parseString(preprocessedLines);
interp.execute(program);
executeHaxeBlock(preprocessedLines);
var currentLineId = {
sourceFile: scriptLines[currentLine].sourceFile,
lineNumber: scriptLines[currentLine].lineNumber
};
trace(startingId);
trace(currentLineId);
// trace(startingId);
// trace(currentLineId);
if (startingId.lineNumber == currentLineId.lineNumber && startingId.sourceFile == currentLineId.sourceFile) {stepLine();}
}
@@ -465,13 +465,13 @@ class Story {
var line = scriptLines[idx++];
if (line.sourceFile == id.sourceFile && line.lineNumber == id.lineNumber) {
gotoLine(idx);
debugTrace('Found the right line');
// debugTrace('Found the right line');
}
}
}
private function stepLine() {
debugTrace('stepLine called');
// debugTrace('stepLine called');
if (!finished) {
// debugTrace('Stepping to line ${Std.string(scriptLines[currentLine+1])}');
gotoLine(currentLine+1);
@@ -541,7 +541,7 @@ class Story {
private function queueEmbeddedBlock(dummyFile: String) {
if (embeddedBlocksQueued.length == 0) {
trace('${dummyFile} got here first');
// trace('${dummyFile} got here first');
gotoFile(dummyFile);
}
embeddedBlocksQueued.push(dummyFile);
@@ -551,14 +551,14 @@ class Story {
private function processEmbeddedLines(parent: LineID, childNumber: Int, lines: String) {
embeddedEntryPoint = parent;
var dummyFile = 'EMBEDDED BLOCK ${childNumber}/${Std.string(parent)}';
debugTrace('processing ${dummyFile}');
// debugTrace('processing ${dummyFile}');
queueEmbeddedBlock(dummyFile);
}
/** Execute a parsed script statement **/
private function processLine(line: HankLine): StoryFrame {
if (line.type != NoOp) {
debugTrace('Processing ${Std.string(line)}');
// debugTrace('Processing ${Std.string(line)}');
}
var file = line.sourceFile;
@@ -604,7 +604,7 @@ class Story {
stepLine();
embeddedEntryPoint = null;
} else {
trace('another block was queued');
// trace('another block was queued');
var nextBlock = embeddedBlocksQueued[0];
gotoFile(nextBlock);
}
@@ -641,7 +641,7 @@ class Story {
return Error("Trust me, you'd rather not use a triple-nested Haxe block");
}
processHaxeBlock(code);
trace('done that');
// trace('done that');
return Empty;
// Execute choice declarations by collecting the set of choices and presenting valid ones to the player
@@ -846,12 +846,33 @@ class Story {
private function checkChoiceCondition(choice: Choice): Bool {
return if (Util.startsWithEnclosure(choice.text, "{", "}")) {
var conditionExpression = Util.findEnclosure(choice.text, "{", "}");
var parsed = parser.parseString(conditionExpression);
var conditionValue = interp.expr(parsed);
var conditionValue = evaluateHaxeExpression(conditionExpression);
conditionValue;
} else true;
}
private function evaluateHaxeExpression(expression: String) {
// It's common to want to && or || section/label names, but they're integers, not bools. Allow this.
var expandedExpression = expression;
var parsed = parser.parseString(expandedExpression);
try {
var value = interp.expr(parsed);
return value;
} catch (e: Dynamic) {
throw 'Error evaluating expression ${expression}: ${Std.string(e)}';
}
}
private function executeHaxeBlock(block: String) {
try {
var program = parser.parseString(block);
interp.execute(program);
} catch (e: Dynamic) {
throw 'Error evaluating haxe block: ${Std.string(e)}\n${block}';
}
}
/**
Process a choice into the desired form to show the player
@param chosen Whether to show the choice's "before" or "after" text to the player
@@ -901,9 +922,8 @@ class Story {
Skip script execution to the desired target
**/
public function divert(target: String): StoryFrame {
debugTrace('diverting to ${target}');
// debugTrace('diverting to ${target}');
// TODO check the current section for a subsection by the name of target, or else parse . notation for subsections
// TODO if going to a labeled gather, set the choice depth to that gather's depth - 1
// debugTrace('going to section ${section}');
// Update this section's view count
if (!interp.variables.exists(target)) {

View File

@@ -14,22 +14,19 @@ class StoryTestCase extends utest.Test {
private function validateAgainstTranscript(storyFile: String, transcriptFile: String, fullTranscript: Bool = true, debug: Bool = false, debugPrints: Bool = false) {
trace('validating ${storyFile}');
if (debugPrints) trace('validating ${storyFile}');
var story: Story = new Story(debug,'validating.hanktest', debugPrints);
var story: Story = new Story(debug,'validating.hlog', debugPrints);
story.loadScript(storyFile);
var transcriptLines = sys.io.File.getContent(transcriptFile).split('\n');
var i = 0;
while (i < transcriptLines.length) {
var line = transcriptLines[i];
trace(line);
var frame = story.nextFrame();
if (debugPrints) {
if (debugPrints) {
trace('Frame ${i}: ${Std.string(frame)}');
}
trace('Frame ${i}: ${Std.string(frame)}');
}
if (StringTools.startsWith(line, "*")) {
@@ -76,6 +73,6 @@ class StoryTestCase extends utest.Test {
// After all transcript lines are validated, there should be nothing left in the story flow!
Assert.equals(StoryFrame.Finished, story.nextFrame());
}
trace('done with ${storyFile}');
if (debugPrints) trace('done with ${storyFile}');
}
}

View File

@@ -13,23 +13,35 @@ class StoryTest extends src.StoryTestCase {
public function testParseHelloWorld() {
var story: Story = new Story();
story.loadScript("examples/hello.hank"); assertComplexEquals(OutputText('Hello, world!'), story.scriptLines[0].type);
story.loadScript("examples/hello/main.hank"); assertComplexEquals(OutputText('Hello, world!'), story.scriptLines[0].type);
}
public function testHelloWorld() {
var story: Story = new Story();
story.loadScript("examples/hello.hank");
story.loadScript("examples/hello/main.hank");
assertComplexEquals(HasText("Hello, world!"), story.nextFrame());
Assert.equals(StoryFrame.Finished, story.nextFrame());
Assert.equals(StoryFrame.Finished, story.nextFrame());
}
public function testRunFullSpec2() {
validateAgainstTranscript("examples/main.hank", "examples/tests/main1.hanktest");
}
public function testAllExamples() {
var exampleFolders = sys.FileSystem.readDirectory('examples');
public function testRunFullSpec3() {
validateAgainstTranscript("examples/main.hank", "examples/tests/main2.hanktest");
// Iterate through every example in the examples folder
for (folder in exampleFolders) {
trace('Running tests for example "${folder}"');
var files = sys.FileSystem.readDirectory('examples/${folder}');
for (file in files) {
if (StringTools.endsWith(file, '.hlog')) {
trace(' Running ${file}');
var debug = file.indexOf("debug") != -1;
var partial = file.indexOf("partial") != -1;
validateAgainstTranscript('examples/${folder}/main.hank', 'examples/${folder}/${file}', !partial, debug, false);
}
}
}
}
/**
@@ -37,8 +49,8 @@ class StoryTest extends src.StoryTestCase {
**/
public function testRunFullSpec1() {
trace('testing the main hank example manually');
var story: Story = new Story(true, "transcript.hanktest", true);
story.loadScript("examples/main.hank");
var story: Story = new Story(true, "transcript.hlog", true);
story.loadScript("examples/main/main.hank");
var frame1 = story.nextFrame();
// This calls the INCLUDE statement. Ensure that all lines
// were included
@@ -82,12 +94,12 @@ class StoryTest extends src.StoryTestCase {
Assert.equals(StoryFrame.Finished, story.nextFrame());
// Validate the transcript that was produced
validateAgainstTranscript("examples/main.hank", "transcript.hanktest");
validateAgainstTranscript("examples/main/main.hank", "transcript.hlog");
}
public function testViewCounts() {
var story = new Story(true);
story.loadScript("examples/main.hank");
story.loadScript("examples/main/main.hank");
Assert.equals(0, story.interp.variables['start']);
Assert.equals(0, story.interp.variables['choice_example']);
@@ -106,7 +118,7 @@ class StoryTest extends src.StoryTestCase {
public function testParseFullSpec() {
// Parse the main.hank script and test that all lines are correctly parsed
var story = new Story(true);
story.loadScript("examples/main.hank");
story.loadScript("examples/main/main.hank");
Assert.equals(40+22, story.lineCount);
// TODO test a few line numbers from the script to make sure the parsed versions match. Especially block line numbers
@@ -116,7 +128,7 @@ class StoryTest extends src.StoryTestCase {
var lineTypes = [
// TODO the 22 lines of the extra.hank file
IncludeFile('examples/extra.hank'),
IncludeFile('examples/main/extra.hank'),
NoOp,
Divert('start'),
NoOp,
@@ -156,7 +168,7 @@ class StoryTest extends src.StoryTestCase {
OutputText("These should all say 'mouse':"),
OutputText("{what_happened}"),
OutputText("{variable_declared_in_block}"),
EOF('examples/main.hank')
EOF('examples/main/main.hank')
];
var idx = 23;
@@ -165,47 +177,4 @@ class StoryTest extends src.StoryTestCase {
assertComplexEquals(lineTypes[i++], story.scriptLines[idx++].type);
}
}
@Ignored
public function testRunIntercept1() {
validateAgainstTranscript("examples/TheIntercept.hank", "examples/tests/intercept1.hanktest", false,
false,
true);
}
@Ignored
public function testRunInterceptDebug1() {
validateAgainstTranscript(
"examples/TheIntercept.hank",
"examples/tests/interceptDebug1.hanktest",
false, // Don't validate all of the Intercept until the port is done
true, // Set DEBUG to true
true); // Use debugTrace statements
}
public function testEmbeddedHankMindfuck() {
// Test the situation where embedded Hank lines are triggered, and later the story loops to the same Haxe block with different conditions
validateAgainstTranscript("examples/mindfuck.hank", "examples/tests/mindfuck.hanktest", true, true, true);
}
public function testConditionalBlocks() {
trace('Testing conditional example in production mode');
validateAgainstTranscript("examples/conditional.hank", "examples/tests/conditional1.hanktest", true, false, true);
trace('testing conditional example in debug mode');
validateAgainstTranscript("examples/conditional.hank", "examples/tests/conditionalDebug1.hanktest", true, true, true);
}
public function testLabels() {
validateAgainstTranscript("examples/labels.hank", "examples/tests/labels1.hanktest");
validateAgainstTranscript("examples/labels.hank", "examples/tests/labels2.hanktest");
}
/** Test one of Nat's private WIP Hank stories **/
public function testPrivateStories() {
if (sys.FileSystem.exists('examples/shave')) {
validateAgainstTranscript('examples/shave/shave-draft2.hank', 'examples/shave/tests/1.hanktest');
} else {
Assert.isTrue(true);
}
}
}