Grammar Data Gen - Instructions
Grammar Data Gen is a small browser app for practicing exploratory testing of grammar-driven generated text.
About The App
Grammar Data Gen - Basic is the simple buggy version. It generates random text from grammar definitions. Each definition can contain one or more lines. Each line can contain bracketed phrase groups, for example:
We can [only, never, absolutely] [automate, encourage, mandate] [creativity, rote work, the wearing of hats]
When the app generates text it chooses one grammar line, then chooses one value from each bracketed group.
Both Grammar Data Gen apps deliberately contain bugs. Use them to practice identifying defects, building a test model, and creating focused automated checks.
Grammar Data Gen - Complex also generates random text from grammar templates. It supports the same bracketed option syntax as Basic, but also lets you define named phrase lists:
phrase_insert: [when, we might choose to, "optional quotes, because i added a comma"]
this is a phrase with a #phrase_insert
Lines in the form name: [option one, option two] define reusable phrase data. They are not meant to be generated directly. Template lines can use #name to insert a value from a named phrase list, and successful generated values are shown in a history list.
Phrase lists can refer to other phrase lists:
nums: [one, two, three]
phrase: [over, above, #nums]
this is a #phrase
That can generate this is over, this is above, this is one, this is two, or this is three.
For a fun implementation of a grammar based data generation example check out eviltester.com/sloganizer.
If you want a less buggy version that is practical for actually generating data, check out Grammar Based Test Data in the Tools section.
Things To Explore
- generate many values from the default grammar and watch for errors or repeated patterns
- add several grammar lines and check whether all lines can be selected
- try grammar lines with no bracketed values
- try embedded bracket groups, for example
[bob, and [gain, lose] something] - try empty lines and whitespace-only input
- click around the page while watching whether the generated value changes
- inspect the DOM after expanding the grammar editor
- compare behaviour with the Tools section version
Console Exploration Examples
Use the browser DevTools to explore the app from several angles:
- view source and identify the button that calls
changeSlogan() - inspect the DOM and find the grammar text area, the generated output, and the Complex version history area
- use the console to call
changeSlogan()directly - inspect the configured
sloganizerobject after clicking Generate Grammar - compare
sloganizer.getSlogan()withsloganizer.slogans[0].getSlogan() - use the Sources or Debugger panel to inspect the JavaScript and set breakpoints
A Sloganizer-style grammar can be modelled in Grammar Data Gen Complex with phrase definitions and a template line:
start: ["", Of course, I honestly believe, I really do think]
im_not: [evil, good, nasty, unpleasant]
#start I'm not #im_not
This can generate outputs such as:
I'm not good
Of course I'm not nasty
I really do think I'm not evil
After the page has loaded a grammar, try generating values from the console:
for (var x = 0; x < 100; x++) {
console.log(sloganizer.getSlogan());
}
Try exercising the visible UI repeatedly:
var grammarBot = setInterval(function() {
changeSlogan();
}, 1000);
Stop it with:
clearInterval(grammarBot);
Try a larger random sample:
for (var x = 0; x < 1000; x++) {
console.log("-" + sloganizer.getSlogan());
}
Generate only the first configured template:
for (var x = 0; x < 100; x++) {
console.log("-" + sloganizer.slogans[0].getSlogan());
}
Change the visible generated output directly:
document.getElementById("slogan").innerText = sloganizer.slogans[0].getSlogan();
That direct DOM change is deliberately incomplete because it does not use the app’s normal generation function. Use the app function when you want the page state to stay closer to normal user behaviour:
changeSlogan();
Create a bot that generates from the first configured template:
var firstTemplateBot = setInterval(function() {
document.getElementById("slogan").innerText = sloganizer.slogans[0].getSlogan();
}, 1000);
Stop it with:
clearInterval(firstTemplateBot);
You can also experiment with the app data. Replace the grammar text area with a new template and phrase lists, then generate output from your new grammar:
document.getElementById("slogandefinition").value = [
"i_do_like: [I like, I hate, I despise, I loathe, I love]",
"i_do_like_doing: [eating, smashing, feeding, teasing, tickling, destroying, making, teaching]",
"i_like_doing_with: [systems, managers, testers, developers, code, beliefs, memories, attitudes]",
"#i_do_like #i_do_like_doing #i_like_doing_with"
].join("\n");
configureSloganizer();
for (var x = 0; x < 100; x++) {
console.log(sloganizer.getSlogan());
}
Useful questions:
- What output patterns repeat?
- Which phrase lists create malformed or surprising text?
- What happens if a template references a missing phrase key?
- What happens if a phrase references itself?
- Does direct DOM manipulation leave any app state stale?
- Are there differences between Basic and Complex?
- Which behaviour is visible in the UI, and which behaviour is only obvious from the code?
Automation Ideas
- check that the generate button updates the output area
- check whether all configured grammar lines can appear over repeated runs
- check whether plain-text grammar lines generate without JavaScript errors
- check whether embedded bracket groups are parsed correctly
- check whether clicking unrelated page controls changes the generated output
- check whether pressing Enter in the grammar name field submits or reloads the page
- compare the Basic version with the Complex version