jcunit's blog

JCUnitの開発日誌(ログ)です。"その時点での"JCUnit作者の理解や考え、開発状況を日本語で書きます。

0.6.0リリース。

長い道のりであったが、0.6.0をリリースした。 Maven coordinateは以下のとおり。

    <dependency>
      <groupId>com.github.dakusui</groupId>
      <artifactId>jcunit</artifactId>
      <version>[0.6.0,)</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>

古いJUnitを使っていると実行時にエラーが出るようなので、JUnitについての依存もバージョンを指定するほうがよいようだ。 今回の新機能は以下の通り。

自分で言うのもなんだが、かなり「使える」水準になってきたと思う。 特にネガティブテストの自動生成は便利だ。

ということで、以前見つけた正規表現逆生成ライブラリxegerのテストを作ってみた。こちら

@RunWith(JCUnit.class)
public class XegerTest {
  @FactorField(stringLevels = {
      ".",
      "A",
      "[A]",
      "[AB]",
      "[A-C]"
  })
  public String characterClass1;

  @FactorField(stringLevels = {
      "?",
      "*",
      "+",
      "{1,2}",
      "{1,3}",
      "{2,3}" })
  public String quantifier1;

  @FactorField(stringLevels = {
      "a",
      "[a]",
      "[ab]",
      "[a-c]" })
  public String characterClass2;

  @FactorField(stringLevels = {
      "?",
      "*",
      "+",
      "{1,2}",
      "{1,3}",
      "{2,3}" })
  public String quantifier2;

  /**
   * 0 ... characterClass1
   * 1 ... quantifier1
   * 2 ... characterClass2
   * 3 ... quantifier2
   */
  @FactorField(stringLevels = {
      "{0}{1}{2}{3}",
      " ({0}{1}{2}){3}",
      " ({0}{1}|{2}){3}",
      " (({0}|{2}){1}){3}"
  })
  public String structure;

  @Test
  public void shouldGenerateTextsThatMatchOriginalRegex() {
    String regex = this.composeRegex();
    Xeger generator = new Xeger(regex, new Random(1));
    for (int i = 0; i < 100; i++) {
      String text = generator.generate();
      assertTrue(
          String.format("Generated text '%s' didn't match regex '%s", text, regex),
          Pattern.compile(
              regex
          ).matcher(text).matches());
    }
  }

  @Test
  public void shouldBeRepeatable() throws InterruptedException {
    int tries = 100;
    int seed = 1;
    String regex = this.composeRegex();
    List<String> first = new ArrayList<String>(tries);
    {
      Xeger generator1 = new Xeger(regex, new Random(seed));
      for (int i = 0; i < tries; i++) {
        first.add(generator1.generate());
      }
    }
    TimeUnit.MILLISECONDS.sleep(1);
    List<String> second = new ArrayList<String>(tries);
    {
      Xeger generator2 = new Xeger(regex, new Random(seed));
      for (int i = 0; i < tries; i++) {
        second.add(generator2.generate());
      }
    }
    assertTrue(
        String.format("Xeger didn't return the same result in spite that the same pattern and seed were given:(pattern=%s, seed=%s)", regex, seed),
        first.equals(second));
  }

  String composeRegex() {
    return MessageFormat.format(
        this.structure,
        this.characterClass1, this.quantifier1,
        this.characterClass2, this.quantifier2
    );
  }
}

こんな風にテストを作るといい感じに2つほどバグが見つかる。

また、今回からドキュメントはWikiにまとめることにした。

github.com

機能追加、改善の要望がもしあれば、

Issues · dakusui/jcunit · GitHub

またはこのブログのコメントにでも寄せてほしい。