Skip to content
Permalink
Browse files

Fix #49

  • Loading branch information...
thiagodp committed Oct 19, 2019
1 parent 7d60525 commit e78f7029734c0295d344f534830f9991f912b7ad
@@ -7,8 +7,8 @@ import { PreTestCaseGenerator, GenContext } from "../../modules/testscenario/Pre
import { SpecFilter } from "../../modules/selection/SpecFilter";
import { BatchSpecificationAnalyzer } from "../../modules/semantic/BatchSpecificationAnalyzer";
import { TestPlanner } from "../../modules/testcase/TestPlanner";
import { JustOneInvalidMix } from "../../modules/testcase/DataTestCaseMix";
import { IndexOfEachStrategy } from "../../modules/selection/CombinationStrategy";
import { JustOneInvalidMix, UnfilteredMix } from "../../modules/testcase/DataTestCaseMix";
import { IndexOfEachStrategy, SingleRandomOfEachStrategy } from "../../modules/selection/CombinationStrategy";
import { TestScenario } from "../../modules/testscenario/TestScenario";
import { LongLimits } from "../../modules/testdata/limits/LongLimits";

@@ -49,12 +49,13 @@ describe( 'TCGen', () => {
let doc1: Document = cp.addToSpec( spec,
[
'#language:pt',
'Feature: Feature 1',
'Scenario: Foo',
'Variant: Foo',
'Funcionalidade: Feature 1',
'Cenário: Foo',
'Variante: Foo',
' Quando eu preencho {A}',
' E eu preencho <b> com "foo"',
' Então eu devo ver "x"',
' Então eu devo ver "x"',
'',
'Elemento de IU: A',
' - valor mínimo é 5',
' Caso contrário, eu devo ver a mensagem "bar"' // <<< oracle
@@ -107,8 +108,161 @@ describe( 'TCGen', () => {
} );


it( 'indicates that it should fail when one of two UI Elements receives an invalid value but it does not have an oracle', async () => {

let spec = new AugmentedSpec( '.' );

let doc1: Document = cp.addToSpec( spec,
[
'#language:pt',
'Funcionalidade: Feature 1',
'Cenário: Foo',
'Variante: Foo',
' Quando eu preencho {A}',
' E eu preencho {B}',
' E eu preencho <c> com "foo"',
' Então eu devo ver "x"',
'',
'Elemento de IU: A',
' - valor mínimo é 5',
' Caso contrário, eu devo ver a mensagem "bar"', // <<< oracle
'',
'Elemento de IU: B',
' - valor mínimo é 5' // <<< no oracle
],
{ path: 'doc1.feature', hash: 'doc1' } as FileInfo
);

const specFilter = new SpecFilter( spec );
const batchSpecAnalyzer = new BatchSpecificationAnalyzer();
let errors: LocatedException[] = [],
warnings: LocatedException[] = [];

await batchSpecAnalyzer.analyze( specFilter.graph(), spec, errors );

// expect( doc1.fileErrors ).toEqual( [] );
// expect( doc2.fileErrors ).toEqual( [] );

const testPlanMakers: TestPlanner[] = [
// new TestPlanMaker( new AllValidMix(), new SingleRandomOfEachStrategy( SEED ) )
new TestPlanner( new UnfilteredMix, new IndexOfEachStrategy( 0 ), SEED )
];

const ctx1 = new GenContext( spec, doc1, errors, warnings );
const variant1: Variant = doc1.feature.scenarios[ 0 ].variants[ 0 ];

let ts = new TestScenario();
ts.steps = variant1.sentences;

const testCases = await gen.generate( ts, ctx1, testPlanMakers );
expect( errors ).toHaveLength( 0 );
expect( testCases ).not.toHaveLength( 0 );

const tc: TestCase = testCases[ 0 ];

// Content + Comment
const lines = tc.sentences.map( s => s.content + ( ! s.comment ? '' : ' #' + s.comment ) );
const value1 = LongLimits.MIN;
const comment1 = '# {A}, inválido: menor valor aplicável';
const value2 = LongLimits.MIN;
const comment2 = '# {B}, inválido: menor valor aplicável';

expect( lines ).toEqual(
[
'Quando eu preencho <a> com ' + value1 + ' ' + comment1,
'E eu preencho <b> com ' + value2 + ' ' + comment2,
'E eu preencho <c> com "foo"',
'Então eu devo ver a mensagem "bar" # de <a>' // << Then replaced with the oracle
]
);

expect( tc.shouldFail ).toBeTruthy();

} );


it( 'indicates that it should fail when one of three UI Elements receives an invalid value but it does not have an oracle', async () => {

let spec = new AugmentedSpec( '.' );

let doc1: Document = cp.addToSpec( spec,
[
'#language:pt',
'Funcionalidade: Feature 1',
'Cenário: Foo',
'Variante: Foo',
' Quando eu preencho {A}',
' E eu preencho {B}',
' E eu preencho {C}',
' E eu preencho <d> com "foo"',
' Então eu devo ver "x"',
'',
'Elemento de IU: A',
' - valor mínimo é 5',
' Caso contrário, eu devo ver a mensagem "bar"', // <<< oracle
'',
'Elemento de IU: B',
' - valor mínimo é 5',
' Caso contrário, eu devo ver a mensagem "zoo"', // <<< oracle
'',
'Elemento de IU: C',
' - valor mínimo é 5' // <<< no oracle
],
{ path: 'doc1.feature', hash: 'doc1' } as FileInfo
);

const specFilter = new SpecFilter( spec );
const batchSpecAnalyzer = new BatchSpecificationAnalyzer();
let errors: LocatedException[] = [],
warnings: LocatedException[] = [];

await batchSpecAnalyzer.analyze( specFilter.graph(), spec, errors );

// expect( doc1.fileErrors ).toEqual( [] );
// expect( doc2.fileErrors ).toEqual( [] );

const testPlanMakers: TestPlanner[] = [
// new TestPlanMaker( new AllValidMix(), new SingleRandomOfEachStrategy( SEED ) )
new TestPlanner( new UnfilteredMix, new IndexOfEachStrategy( 0 ), SEED )
];

const ctx1 = new GenContext( spec, doc1, errors, warnings );
const variant1: Variant = doc1.feature.scenarios[ 0 ].variants[ 0 ];

let ts = new TestScenario();
ts.steps = variant1.sentences;

const testCases = await gen.generate( ts, ctx1, testPlanMakers );
expect( errors ).toHaveLength( 0 );
expect( testCases ).not.toHaveLength( 0 );

const tc: TestCase = testCases[ 0 ];

// Content + Comment
const lines = tc.sentences.map( s => s.content + ( ! s.comment ? '' : ' #' + s.comment ) );
const valueA = LongLimits.MIN;
const commentA = '# {A}, inválido: menor valor aplicável';
const valueB = LongLimits.MIN;
const commentB = '# {B}, inválido: menor valor aplicável';
const valueC = LongLimits.MIN;
const commentC = '# {C}, inválido: menor valor aplicável';

expect( lines ).toEqual(
[
'Quando eu preencho <a> com ' + valueA + ' ' + commentA,
'E eu preencho <b> com ' + valueB + ' ' + commentB,
'E eu preencho <c> com ' + valueC + ' ' + commentC,
'E eu preencho <d> com "foo"',
'Então eu devo ver a mensagem "bar" # de <a>', // << Then replaced with the oracle
'E eu devo ver a mensagem "zoo" # de <b>' // << Then replaced with the oracle
]
);

expect( tc.shouldFail ).toBeTruthy();
} );


it( 'indicates that should fail when no Otherwise is declared and has Then sentence withou state', async () => {
it( 'indicates that should fail when no Otherwise is declared and has Then sentence without state', async () => {

let spec = new AugmentedSpec( '.' );

@@ -27,7 +27,7 @@ class TestPlanner {
* Produces test plans, i.e., maps from UI Elements variables to UIETestPlan, in which
* the expected result and oracles are embedded.
*
* @param map A map from UI Element Variables to anoher map containing all
* @param map A map from UI Element Variables to another map containing all
* available DataTestCases and their respective expected result
* (valid, invalid or incompatible) and Oracle steps (if applicable).
*
@@ -7,10 +7,12 @@ const NodeTypes_1 = require("../req/NodeTypes");
* @author Thiago Delgado Pinto
*/
class PreTestCase {
constructor(testPlan, steps = [], oracles = []) {
constructor(testPlan, steps = [], oracles = [], // Otherwise steps
correspondingOracles = []) {
this.testPlan = testPlan;
this.steps = steps;
this.oracles = oracles;
this.correspondingOracles = correspondingOracles;
}
hasAnyInvalidValue() {
return this.testPlan.hasAnyInvalidResult();
@@ -25,7 +27,7 @@ class PreTestCase {
}
return null;
}
hasThenStep() {
hasAnyThenStep() {
return this.lastThenStep() !== null;
}
stepsBeforeTheLastThenStep() {
@@ -46,9 +48,22 @@ class PreTestCase {
return (this.oracles || []).length > 0;
}
shouldFail() {
return this.hasThenStep()
&& this.hasAnyInvalidValue()
&& !this.hasOracles();
// return this.hasAnyThenStep()
// && this.hasAnyInvalidValue()
// && ! this.hasOracles();
if (!this.hasAnyThenStep) {
return false;
}
for (let step of this.steps) {
// Is it invalid && it does not have otherwise steps
if (step.isInvalidValue && !this.hasCorrespondingOracles(step)) {
return true;
}
}
return false;
}
hasCorrespondingOracles(step) {
return !!this.correspondingOracles.find(c => c.step === step);
}
}
exports.PreTestCase = PreTestCase;
@@ -230,21 +230,28 @@ class PreTestCaseGenerator {
}
// console.log( 'uieVariableToValueMap', uieVariableToValueMap );
// Steps & Oracles
let completeSteps = [], stepOracles = [];
let filledSteps = [];
let filledOtherwiseSteps = [];
let filledCorrespondingOtherwiseSteps = [];
for (let step of newSteps) {
// Resulting oracles are also processed
let [resultingSteps, resultingOracles] = this.fillUIElementWithValueAndReplaceByUILiteralInStep(step, langContent, plan.dataTestCases, uieVariableToValueMap, language, ctx);
// Resulting otherwiseSteps are also processed
let [resultingSteps, correspondingOtherwiseSteps] = this.fillUIElementWithValueAndReplaceByUILiteralInStep(step, langContent, plan.dataTestCases, uieVariableToValueMap, language, ctx);
// console.log( 'ORACLES', '>'.repeat(10), resultingOracles );
completeSteps.push.apply(completeSteps, resultingSteps);
if (resultingOracles.length > 0) {
stepOracles.push.apply(stepOracles, resultingOracles);
filledSteps.push.apply(filledSteps, resultingSteps);
if (correspondingOtherwiseSteps.length > 0) {
let allOracles = [];
for (let c of correspondingOtherwiseSteps) {
allOracles.push.apply(allOracles, c.otherwiseSteps);
}
filledOtherwiseSteps.push.apply(filledOtherwiseSteps, allOracles);
filledCorrespondingOtherwiseSteps.push.apply(filledCorrespondingOtherwiseSteps, correspondingOtherwiseSteps);
}
}
this.normalizeOracleSentences(stepOracles, langContent.keywords);
this.normalizeOracleSentences(filledOtherwiseSteps, langContent.keywords);
// # (2019-07-13)
this.replaceUIPropertyReferencesInsideValues(completeSteps, stepOracles, uieVariableToValueMap, language, langContent, ctx);
this.replaceUIPropertyReferencesInsideValues(filledSteps, filledOtherwiseSteps, uieVariableToValueMap, language, langContent, ctx);
// ---
all.push(new PreTestCase_1.PreTestCase(plan, completeSteps, stepOracles));
all.push(new PreTestCase_1.PreTestCase(plan, filledSteps, filledOtherwiseSteps, filledCorrespondingOtherwiseSteps));
}
// console.log( all.map( ptc => ptc.steps.map( s => s.content ) ) );
return all;
@@ -362,7 +369,7 @@ class PreTestCaseGenerator {
comment = ' ' + keywordValid + Symbols_1.Symbols.TITLE_SEPARATOR + ' ' + keywordRandom;
}
else {
sentence += entity.string; // UI Element currently doesn't need prefix/sufix
sentence += entity.string; // UI Element currently doesn't need prefix/suffix
}
let newStep = deepcopy(step);
newStep.nodeType = nodeType;
@@ -477,7 +484,10 @@ class PreTestCaseGenerator {
const keywordInvalid = !keywords.invalid ? 'invalid' : (keywords.invalid[0] || 'invalid');
// const keywordRandom = ! keywords.random ? 'random' : ( keywords.random[ 0 ] || 'random' );
const keywordFrom = !keywords.from ? 'from' : (keywords.from[0] || 'from');
let steps = [], oracles = [], line = step.location.line, count = 0;
let steps = [];
let oracles = [];
let line = step.location.line;
let count = 0;
// console.log( 'step', step.content );
const uieNameHandler = new util_1.UIElementNameHandler();
for (let entity of uieEntities) {
@@ -535,6 +545,7 @@ class PreTestCaseGenerator {
// }
const uieTestPlan = uieVariableToUIETestPlanMap.get(variable) || null;
let expectedResult, dtc;
let oraclesToAdd = [];
// console.log( 'uieTestPlan', uieTestPlan );
// Evaluate the test plan and oracles
if (null === uieTestPlan) { // not expected
@@ -552,7 +563,8 @@ class PreTestCaseGenerator {
Symbols_1.Symbols.UI_LITERAL_PREFIX + uieLiteral + Symbols_1.Symbols.UI_LITERAL_SUFFIX;
}
// Add oracles
oracles.push.apply(oracles, oraclesClone);
// oracles.push.apply( oracles, oraclesClone );
oraclesToAdd = oraclesClone; // Save to add later
}
else {
expectedResult = keywordValid;
@@ -597,6 +609,9 @@ class PreTestCaseGenerator {
// Update NLP !
this._variantSentenceRec.recognizeSentences(language, [newStep], ctx.errors, ctx.warnings);
steps.push(newStep);
if (oraclesToAdd.length > 0) {
oracles.push({ step: newStep, otherwiseSteps: oraclesToAdd });
}
++count;
}
return [steps, oracles];
@@ -32,7 +32,7 @@ export class TestPlanner {
* Produces test plans, i.e., maps from UI Elements variables to UIETestPlan, in which
* the expected result and oracles are embedded.
*
* @param map A map from UI Element Variables to anoher map containing all
* @param map A map from UI Element Variables to another map containing all
* available DataTestCases and their respective expected result
* (valid, invalid or incompatible) and Oracle steps (if applicable).
*

0 comments on commit e78f702

Please sign in to comment.
You can’t perform that action at this time.