Another approach to generate test cases

I described a way to generate test cases some time in the past HERE. Recently, I tried another approach which I put in Github as a real example: https://github.com/grzegorzgrzegorz/testcase-generation. This is also using TCases to generate non-executable test cases from model. More about TCases HERE

The concept of the approach is:

  • create model file
  • generate non-executable test cases (by TCases)
  • prepare variable related classes for deserialization
  • generate test cases by using the code which under the hood deserializes non-executable test cases in order to generate executable code

For example: there is an application which converts text into valid sentence, that is makes first letter capitalized and adds dot at the end. If there is variable called Capitals in the model, there has to be class Capitals prepared. This requires some work, but it allows to separate executable code from model. In the code snippet below there is one of the non executable test cases which has Capitals variable set to “NotFirstLetterCapitalized”:

{
                "id": 1,
                "name": "InputContent.Words='ManyWords'",
                "has": {
                    "properties": "inputIsPresent"
                },
                "arg": {
                    "InputIsNotNull": {
                        "value": "Yes"
                    },
                    "InputContent.Words": {
                        "value": "ManyWords"
                    },
                    "InputContent.Dots": {
                        "value": "DotPresentNotAtTheEnd"
                    },
                    "InputContent.Capitals": {
                        "value": "NotFirstLetterCapitalized"
                    }
                }
            },

Information about how to prepare string with regards to capitalization and how to assert it are put into Capitals class:

public class Capitals extends InputContent {

    public Capitals() {
        this("");
    }

    public Capitals(String value) {
        super(value);

        ParameterClosure givenDsl = (String inputValue) -> {
            if (!inputValue.isEmpty()) {
                return "dataGenerator.set(\"" + inputValue + "\");";
            }
            return "//N/A";
        };

        ParameterClosure thenDsl = (String inputValue) -> {
            if (!inputValue.isEmpty()) {
                return "assert result.matches(\"^[A-Z].*\");";
            }
            return "//N/A";
        };

        setGivenDsl(givenDsl);
        setThenDsl(thenDsl);
    }

}

The generated, executable test case looks like this:

@Test
void test1(){ //TestcaseWriter
//GIVEN
DataGenerator dataGenerator = new DataGenerator(); //TestcaseWriter
dataGenerator.set("NotFirstLetterCapitalized"); //Capitals
//Not found: GIVEN //InputIsNotNull
dataGenerator.set("ManyWords"); //Words
dataGenerator.set("DotPresentNotAtTheEnd"); //Dots
//WHEN
//Not found: WHEN //Capitals
String text = dataGenerator.generate(); //InputIsNotNull
//Not found: WHEN //Words
//Not found: WHEN //Dots
String result = MyUtil.makeValidSentence(text); //When
//THEN
assert result.matches("^[A-Z].*"); //Capitals
//N/A //InputIsNotNull
assert result.matches(".*[ ]+.*\\."); //Words
assert result.matches(".*\\.$"); //Dots
} //TestcaseWriter

To sum up: the main advantage of this approach is the separation of DSL syntax and model data. There is much more info on Github: https://github.com/grzegorzgrzegorz/testcase-generation.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *