Author: Grzegorz

  • 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.