javajunitquickcheck

Junit-Quickcheck: Generate String matching a pattern


I am using pholser's port. I have to generate strings matching a given pattern like \[a-zA-Z0-9\\.\\-\\\\;\\:\\_\\@\\[\\]\\^/\\|\\}\\{]* Length 40.

I extend the Generator class as:

public class InputGenerator extends Generator<TestData> {...}

It overloads a function:

publicTestData generate(SourceOfRandomness random, GenerationStatus status) {...}

Now, random has functions like nextDouble(), nextInt() but there is nothing for strings! How can I generate random strings matching the above pattern?


Solution

  • Find below snippet for a custom generator which implement the generate(..) method to return a random string matching your posted pattern.

    public class MyCharacterGenerator extends Generator<String> {
    
        private static final String LOWERCASE_CHARS = "abcdefghijklmnopqrstuvwxyz";
        private static final String UPPERCASE_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        private static final String NUMBERS = "0123456789";
        private static final String SPECIAL_CHARS = ".-\\;:_@[]^/|}{";
        private static final String ALL_MY_CHARS = LOWERCASE_CHARS
                + UPPERCASE_CHARS + NUMBERS + SPECIAL_CHARS;
        public static final int CAPACITY = 40;
    
        public MyCharacterGenerator () {
            super(String.class);
        }
    
        @Override
        public String generate(SourceOfRandomness random, GenerationStatus status) {
            StringBuilder sb = new StringBuilder(CAPACITY);
            for (int i = 0; i < CAPACITY; i++) {
                int randomIndex = random.nextInt(ALL_MY_CHARS.length());
                sb.append(ALL_MY_CHARS.charAt(randomIndex));
            }
            return sb.toString();
        }
    }
    

    edit A simple unit test to demonstrate the usage of the MyCharacterGenerator class.

    import com.pholser.junit.quickcheck.ForAll;
    import com.pholser.junit.quickcheck.From;
    import static org.junit.Assert.assertTrue;
    import org.junit.contrib.theories.Theories;
    import org.junit.contrib.theories.Theory;
    import org.junit.runner.RunWith;
    
    @RunWith(Theories.class)
    public class MyCharacterGeneratorTest {
    
        @Theory
        public void shouldHold(@ForAll @From(MyCharacterGenerator.class) String s) {
            // here you should add your unit test which uses the generated output
            // 
            // assertTrue(doMyUnitTest(s) == expectedResult);
    
            // the below lines only for demonstration and currently
            // check that the generated random has the expected
            // length and matches the expected pattern
            System.out.println("shouldHold(): " + s);
            assertTrue(s.length() == MyCharacterGenerator.CAPACITY);
            assertTrue(s.matches("[a-zA-Z0-9.\\-\\\\;:_@\\[\\]^/|}{]*"));
        }
    }
    

    sample output generated by shouldHold

    shouldHold(): MD}o/LAkW/hbJVWPGdI;:RHpwo_T.lGs^DOFwu2.
    shouldHold(): IT_O{8Umhkz{@PY:pmK6}Cb[Wc19GqGZjWVa@4li
    shouldHold(): KQwpEz.CW28vy_/WJR3Lx2.tRC6uLIjOTQtYP/VR
    shouldHold(): pc2_T4hLdZpK78UfcVmU\RTe9WaJBSGJ}5v@z[Z\
    ...