Java Concordion 子字符串 ("contains") 的解决方法

Workaround for Java Concordion substring ("contains")

如我所见,Concordion 测试框架仅进行精确 strings/numbers 匹配。

是否有任何解决方法来测试结果包含一些子字符串?

例如,我测试服务 returns 格式错误 ERROR 123,测试应该对任何错误号都有效。

为了测试你的逻辑,你可以去 http://www.vogella.com/tutorials/Mockito/article.html

根据所需的输出可读性和您要投入的工作量,有多种答案。

1) 最简单的是使用assert-true来检查子字符串,例如:

The service [returns](- "#result=callService()") an [ERROR](- "c:assert-true=containsSubstring(#result, #TEXT)")

夹具:

@RunWith(ConcordionRunner.class)
public class Whosebug {

    public String callService() {
        // call your service here
    }

    public boolean containsSubstring(String input, String check) {
        return input.contains(check);
    }
}

这样做的缺点是,如果失败,错误消息只会显示:

2) 与 1 相同的夹具,containsSubstring 在失败时抛出异常。然后 Concordion 会将失败显示为堆栈跟踪:

public boolean containsSubstring(String input, String check) {
    if (!input.contains(check)) {
        throw new AssertionError("'" + input + "' does not contain '" + check + "'");
    }
    return true;
}

失败时显示:

3) 使用assertEquals检查:

The service [returns](- "#result=callService()") an [ERROR](- "?=contains(#result, #TEXT)")

夹具:

public String contains(String input, String check) {
    if (!input.contains(check)) {
        return input;
    }
    return check;
}

这显示 "best" 错误消息:

4) 你可以写一个扩展,这样你就不用在每个装置中定义这样一个 contains 方法(或者从一个超类装置中继承它们):

规格:

The service [returns](- "#result=callService()") an [ERROR](- "cx:isError=#result")

夹具:

@RunWith(ConcordionRunner.class)
@ConcordionOptions(declareNamespaces={"cx", "urn:error-extension:2017"})
@Extensions(ErrorExtension.class)
public class Whosebug {

    public String callService() {
        // call your service here
    }
}

分机:

public class ErrorExtension implements ConcordionExtension {
    private List<AssertListener> listeners = new ArrayList<AssertListener>();

    public void addAssertEqualsListener(AssertListener listener) {
        listeners.add(listener);
    }

    public void removeAssertEqualsListener(AssertListener listener) {
        listeners.remove(listener);
    }

    @Override
    public void addTo(ConcordionExtender concordionExtender) {
        concordionExtender.withCommand("urn:error-extension:2017", "isError", new AbstractCommand() {
            @Override
            public void verify(CommandCall commandCall, Evaluator evaluator, ResultRecorder resultRecorder) {
                Check.isFalse(commandCall.hasChildCommands(), "Nesting commands inside an 'isError' is not supported");

                Element element = commandCall.getElement();

                String actual = (String) evaluator.evaluate(commandCall.getExpression());

                if (actual.contains("ERROR")) {
                    resultRecorder.record(Result.SUCCESS);
                    announceSuccess(element);
                } else {
                    resultRecorder.record(Result.FAILURE);
                    announceFailure(element, "String containing ERROR", actual);
                }
            }
        });
        listeners.add(new AssertResultRenderer());
    }

    private void announceSuccess(Element element) {
        for (AssertListener listener : listeners) {
            listener.successReported(new AssertSuccessEvent(element));
        }
    }

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

还显示 "best" 错误消息: