Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance segregation of requirements and implementation #510

Merged
merged 10 commits into from Aug 24, 2014
Expand Up @@ -25,3 +25,27 @@ beat Bill with a noodle

!|script|
|login user with password;|Bob|xyzzy|

!3 Scenarios can be defined without a filler name between the underscores
|scenario | myDivision _ _ _|numerator, denominator, quotient|
|setNumerator| @numerator|
|setDenominator| @denominator|
|check | quotient| @quotient|

Use the Division class from the eg library to implement the scenario
|Library|
|eg.Division|

Test the scenario with a decision table
| myDivision |
| # | numerator | denominator | quotient? |
| any comment| 10 | 2 | 5.0 |


Test the scenario with a script
|script|
|myDivision 20 5 4.0|
|myDivision |6|| 3|| 2.0|
|#| open Bug: The next syntax fails|
|#|myDivision; |10 2 5.0|

@@ -0,0 +1,9 @@
| Division |
| numerator | denominator | quotient? |
| 10 | 2 | 5.0 |
| 12.6 | 3 | 4.2 |
| 22 | 7 | ~=3.14 |
| 9 | 3 | <5 |
| 11 | 2 | 4<_<6 |
| 100 | 4 | 25.0 |
| 25.0 | 5 | 5.0|
@@ -0,0 +1,13 @@
<?xml version="1.0"?>
<properties>
<Edit>true</Edit>
<Files>true</Files>
<Help>A sub page with requirements for a calculator.</Help>
<Properties>true</Properties>
<RecentChanges>true</RecentChanges>
<Refactor>true</Refactor>
<Search>true</Search>
<Suites></Suites>
<Versions>true</Versions>
<WhereUsed>true</WhereUsed>
</properties>
@@ -0,0 +1,31 @@
One of the key goals of FitNesse is to encourage that requirements in FitNesse are written before the coding of the implementation starts.
Having said that the defintion of the requirements must be independent of the technical solution used to implement it.
This sample page shows that the same requirement defintion can be implemented once with a java class implementing the decision table protokoll and once with a senario.


The requirements are defined in a decision table on a sub page.
The first implementation used is the Devision class from the eg library.
|import|
|eg|

!include >CalculatorRequirements


Now we define a second technical solution using a FitNesse scenario
|scenario | Division _ _ _|numerator, denominator, quotient|
|setNumerator| @numerator|
|setDenominator| @denominator|
|check | quotient| @quotient|


Generate an instance of the class used by the scenario:
| Library |
| eg.Division|

|script | Division|


We retest the requirements and get the same results.
Also the output is differently printed.

!include >CalculatorRequirements
@@ -0,0 +1,13 @@
<?xml version="1.0"?>
<properties>
<Edit>true</Edit>
<Files>true</Files>
<LastModifyingUser>sa</LastModifyingUser>
<Properties>true</Properties>
<RecentChanges>true</RecentChanges>
<Refactor>true</Refactor>
<Search>true</Search>
<Test>true</Test>
<Versions>true</Versions>
<WhereUsed>true</WhereUsed>
</properties>
@@ -1,4 +1,4 @@
The amount of exceptions counted should not exceed the number of errors displayed on the screen.
!3 The amount of exceptions counted should not exceed the number of errors displayed on the screen.

!| script |
| given page | TestPage | with content | ${SUT_PATH} !-
Expand All @@ -9,3 +9,24 @@ The amount of exceptions counted should not exceed the number of errors displaye
|consectetur|adipiscing|elit|
-! |
| test results for page | TestPage | should contain | 0 right, 0 wrong, 0 ignored, 7 exceptions |

!3 If a fixture defnition generates a syntax error this must be counted as exception in the test summary.

Syntax errors are generated by:
* A scenario without a name
* A decision table with less than 3 rows

!| script |
| given page | TestPage | with content | ${SUT_PATH} !-
!define TEST_SYSTEM {slim}

|scenario|

|eg.Division|
|nominator|

-! |
| test results for page | TestPage | should contain | 0 right, 0 wrong, 0 ignored, 2 exceptions |
| ensure | content contains | Bad table! Scenario tables must have a name.|
| ensure | content contains | Division: Bad table! DecisionTables should have at least|

@@ -1,3 +1,8 @@
!2 Variables are always passed "by reference" and not "by value"
if a variable is changed on a sub page and then referenced again on the parent page the variable has the value assigned on the sub page and not the value from the parent page.

This behaviour is shown in the below examples:

!3 Define initial values for numerator, denominator and quotient
!define numerator {10}
!define denominator {1}
Expand All @@ -7,25 +12,32 @@
!include >VariablesRedefinedMultipleTimesOnSamePageAndUsedInSubpage

!3 Check values from variables and symbols
|eg.Division|
|# Test Description | numerator | denominator | quotient? |
|Value as defined on this page| ${numerator} | 1 | 10.0 |
|Value as defined on sub page| ${denominator} | 1 | 2.5 |
|Value from sub sub page expression| ${quotient4} | 1 | 4.0|
|Value as defined on sub sub page| ${result} | 1 | 77.0|
|Symbol from sub sub page | $result | 1 | 4.0|
|script|
| #| $ {numerator} has the value as defined on this page|
|check | echo | ${numerator} | 10 |
| #| $ {denominator} has the value as defined on the sub page|
|check | echo | ${denominator} | 2.5 |
| #| $ {quotient4} has the value from expression on the sub sub page|
|check | echo | ${quotient4} | 4.0 |
| #| $ {result} has the value as defined on the sub sub page|
|check | echo | ${result} | 77.0 |
|#| $ result Symbol from sub sub page can be accessed|
|check | echo | $result | 4.0|

!3 Redefine numerator
!define numerator {20}

!include >VariablesRedefinedMultipleTimesOnSamePageAndUsedInSubpage

!3 Check values from variables and symbols again
|eg.Division|
|# Test Description | numerator | denominator | quotient? |
|Value as defined on this page| ${numerator} | 1 | 20.0 |
|Value as defined on sub page| ${denominator} | 1 | 2.5 |
|Value from sub sub page expression| ${quotient4} | 1 | 8.0|
|Value as defined on sub sub page| ${result} | 1 | 77.0|
|Symbol from sub sub page | $result | 1 | 8.0|

|script|
| #| $ {numerator} has the value as defined on this page|
|check | echo | ${numerator} | 20 |
| #| $ {denominator} has the value as defined on the sub page|
|check | echo | ${denominator} | 2.5 |
| #| $ {quotient4} has the value from expression on the sub sub page|
|check | echo | ${quotient4} | 8.0 |
| #| $ {result} has the value as defined on the sub sub page|
|check | echo | ${result} | 77.0 |
|#| $ result Symbol from sub sub page can be accessed|
|check | echo | $result | 8.0|
Expand Up @@ -2,6 +2,7 @@
<properties>
<Edit>true</Edit>
<Files>true</Files>
<LastModifyingUser>sa</LastModifyingUser>
<Properties>true</Properties>
<RecentChanges>true</RecentChanges>
<Refactor>true</Refactor>
Expand Down
3 changes: 2 additions & 1 deletion src/fitnesse/testsystems/slim/HtmlSlimTestSystem.java
Expand Up @@ -51,7 +51,8 @@ protected void processAllTablesOnPage(TestPage pageToTest) throws IOException {
processTable(theTable);
} catch (SyntaxError e) {
String tableName = theTable.getTable().getCellContents(0, 0);
theTable.getTable().updateContent(0, 0, SlimTestResult.fail(String.format("%s: <strong>Bad table! %s</strong>", tableName, e.getMessage())));
theTable.getTable().updateContent(0, 0, SlimTestResult.error(String.format("<strong> %s: Bad table! %s</strong>", tableName, e.getMessage())));
getTestContext().incrementErroredTestsCount();
}

String html = createHtmlResults(startWithTable, nextTable);
Expand Down
6 changes: 6 additions & 0 deletions src/fitnesse/testsystems/slim/tables/DecisionTable.java
Expand Up @@ -77,6 +77,12 @@ private Map<String, String> getArgumentsForRow(int row) {
String valueToSet = table.getCellContents(col, row);
scenarioArguments.put(disgracedVar, valueToSet);
}
for (String var : funcStore.getLeftToRightAndResetColumnNumberIterator()) {
String disgracedVar = Disgracer.disgraceMethodName(var);
int col = funcStore.getColumnNumber(var);
String valueToSet = table.getCellContents(col, row);
scenarioArguments.put(disgracedVar, valueToSet);
}
return scenarioArguments;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/fitnesse/testsystems/slim/tables/ScenarioTable.java
Expand Up @@ -25,7 +25,7 @@

public class ScenarioTable extends SlimTable {
private static final String instancePrefix = "scenarioTable";
private static final String underscorePattern = "\\W_(?:\\W|$)";
private static final String underscorePattern = "\\W_(?=\\W|$)";
private String name;
private List<String> inputs = new ArrayList<String>();
private Set<String> outputs = new HashSet<String>();
Expand Down
6 changes: 5 additions & 1 deletion test/fitnesse/slim/StackTraceEnricherTest.java
Expand Up @@ -161,7 +161,11 @@ public void shouldParseDirectories() {
if (testLocation.endsWith("/")) {
testLocation = testLocation.substring(0, testLocation.length() - 1);
}
assertTrue("Location of unit test (" + testLocation + ") not found on the classpath.",
// Under Windows a path with a SPACE has "%20" in the testLocation and " " in the classpath
// Fix this before the test
testLocation = testLocation.replace("%20", " ");

assertTrue("Location of unit test (" + testLocation + ") not found on the classpath (" + classPath + ").",
classPath.contains(testLocation));
} else {
// TODO Find a way to test this if the unit test is executed from a jar.
Expand Down