سؤال

At some stage in a concordion test I have, I set a value to some random number.

This value is passed along, and later on , I have some output. The output is "checked" using the concordion "table" setup, where i compare an output value to what I expect it to be.

The problem I have is that I would like to check against the random number mentioned above. When I get the random number, I can set it to something Concordion can store -

<span c:set="#prefixValue">Bob</span>

Well, you get the idea - I replace "Bob" with a getter for my value.

But when I try to use it:

<table c:execute="#actual = getValue(#report, #xpath)">
    <tr>
        <th>Field name</th>
        <th c:assertEquals="#actual">Value</th>
        <th c:set="#xpath">Xpath</th>
    </tr>
    <tr>
        <td>UnrelatedValue</td>
        <td>SomeDeterminateValue</td>
        <td>theXpathForThisToCompareTo</td>
    </tr>
    <tr>
        <td>prefix</td>
        <td><span c:echo="#prefixValue" /></td>
        <td>differentXpathForThisToCompareTo</td>
    </tr>

The whole shebang grinds to a halt, complaining that

" Commands must be placed on elements when using 'execute' or 'verifyRows' commands on a <table>. "

How can I use a pre-determined value in a table in Concordion?

هل كانت مفيدة؟

المحلول 2

Oh Lord! I didn't realise Concordion was going to get all rigid on me.

To fix, I had to alter the Concordion method I was using to be less stupidly rigid.

Following the general ideas here: http://automatingsoftwaretesting.wordpress.com/2011/05/27/write-your-own-concordion-command-an-example-for-asserting/

I wrote this:

@Override
public void verify(CommandCall commandCall, Evaluator evaluator, ResultRecorder resultRecorder) {
    Object expected = evaluator.evaluate(commandCall.getChildren().get(0).getExpression());
    Object actual = evaluator.evaluate(commandCall.getExpression());

    Element element = setupTheGoshDarnElement(commandCall, expected);

    if (actual.equals(expected)) {
        resultRecorder.record(Result.SUCCESS);
        announceSuccess(element);
    } else {
        resultRecorder.record(Result.FAILURE);
        announceFailure(element, expected.toString(), actual);
    }
}

private Element setupTheGoshDarnElement(CommandCall commandCall, Object expected) {
    Element e = commandCall.getElement();
    e.appendText(expected.toString());
    return e;
}

private void announceFailure(Element element, String expected, Object actual) {
    listeners.announce().failureReported(new AssertFailureEvent(element, expected, actual));
}

private void announceSuccess(Element element) {
    listeners.announce().successReported(new AssertSuccessEvent(element));
}

And so made a new "evaluator" ~ the rest of the evaluator is identical to the AssertEqualsCommand, if you're wondering.

This neatly checks the element and evaluates. Why concordion didn't do this ~ it isn't rocket science at all ~ is beyond me!

NOTE that I still need to use the "expanded table" in my question to get this to work, the short-form table has it's own issues with evaluating inner expressions.

نصائح أخرى

The specs aren't supposed to have random elements in them. They're supposed to contain a specific example or set of examples. Rather than using a random number, hardcode a particular value and then you can use it later on.

To tell the fixture about the hardcoded value you can do this:

<span c:execute="setPrefixValue(#TEXT)">Bob</span>

Then in the fixture:

public void setPrefixValue(String prefixValue) {
    // TODO: Whatever system configuration you need to do
}

If it isn't actually possible to set the value in your system under test, then use your fixture code to map between the hardcoded value and the actual random value.

public String getValue(String report, String xpath) {
    String value = report(report).get(xpath);
    if (value.equals(knownRandomValue)) {
        return hardcodedValue;
    }
    return value;
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top