开发者

Unit testing when the output is a wall of text

开发者 https://www.devze.com 2023-04-12 11:46 出处:网络
I am currently testing a part of my application (that we will assume is a class named X) that takes as parameter a reflection java Method, and will print some java code based on it (that is, it is a c

I am currently testing a part of my application (that we will assume is a class named X) that takes as parameter a reflection java Method, and will print some java code based on it (that is, it is a code generator). For instance, when passing String.toString() to X, the rendered string output would be:

public static java.lang.String toString(String thisObj, boolean isMonitoring) {
    String thisObjOld = (String)thisObj.clone(thisObj, false);

    if (isMonitoring) {
        toStringPre(thisObj);
    }

    java.lang.String result = thisObj.toString_Original();

    if (isMonitoring) {
        toStringPost(thisObj, thisObjOld, result);
    }

    return result
}

Now, I am wondering how to test this output. I'd like to test different things (individually).

I know the perfect thing to do would be to make assertions against an abstract representation, just before the printing, instead of the final text. But unfortunately, it seems that would be just too much work to set up.

Examples of things I'm looking to test are:

  • If the r开发者_如何学编程eturn type is correct (java.lang.String);
  • If the method's name is correct (toString), as well as its parameters `(String thisObj, boolean isMonitoring).

How to better approach this? Using regular expressions? Using String.split()?


What about compiling the generate code - Test that the code is syntactic correct.

Then use Reflection to check the Name, Parameter and Return type.

Then run it in a Mocked environment to check that it does what it should do.


I think if the generated code is very deterministic (and from looking at your question, it does look deterministic), then I would firstly hand write the correct string output from X, and do a string comparison.

E.g., a junit example:

public void testX(){
   X gnerator = new X(getTestMethodObject());
   Assert.assertEquals(StringUtils.readFully(new File("expected_output.txt")), generator.generate());
}

Obviously, that will perform string comparisons, and when the generated contents change, you'd have to hand write the new expected output. Hence, while this is simple, it could become a maintenance nightmare later on.

The other way, of course, is to lex the generated output and check the tokens generated (i m assuming you can't actually compile the generated code in your test env). Say, http://code.google.com/p/java-lexer/ which is a really simple lexor (i dont vouch for it - i just found it in a couple of minutes of googling...but it has some basic tests, so i assume its good?). Or, use something more complex like antlr which is probably overkill for testing.

I personally would stick with comparing hand written expected output with generated output. Its much lower key, and easier to spot errors than using full blown lexors.


Why don't you 1) compile the generated code and use reflection to assert the "semantics", or, if compiling and loading is not possible due to dependencies and stuff, 2) use a JAVA parser to create an abstract syntax tree that you can traverse and make assertions. (The ANTLR project has grammars for JAVA 6, for example).

0

精彩评论

暂无评论...
验证码 换一张
取 消