Movable TypeのテストデータをPythonスクリプトを使って自動生成してみる

「Movable Type Advent Calendar 2024」の22日目です。

今回のテーマは、Movable Type（以下MT）のテストデータをPythonスクリプトを使って自動生成する方法についてです。

## テストデータの必要性
MTでサイトを構築する際、多くの方が以下のようなフローで作業を進めているのではないでしょうか？

* カスタムフィールドやコンテンツタイプを作成
サイト独自の要件に合わせた構造を構築
* テンプレートの作成
デザインや機能を実現するためにテンプレートを作成
* テストデータを入力して確認
実際にデータを入力して動作確認やレイアウトの検証

特に3つ目の「テストデータの作成」は、多くの現場では手動で行われることが多いように感じます。
たとえば、投稿記事をいくつも作成して、動作を確認する作業が典型例です。

しかし、手動でのデータ作成には以下のような課題があります。

* データをたくさん用意するのに時間がかかる
* ランダム性がないため、意図せず偏ったデータでテストしてしまう
* 本番に近い状況を再現しようとしても、どうしても限界がある

これでは効率的なテストが難しく、思わぬバグを見逃してしまうことも考えられます。

## テストデータの自動生成の必要性

例えば、「30件の記事ごとに無限スクロールするページ」の動作を確認する際、実際に30件以上のデータが必要になります。
これを手動で作成するのは非常に大変です。
テンプレートを一時的に修正して同じ記事を繰り返し表示させる方法もありますが、これでは現実的なデータを元にしたテストができません。

また、以下のような問題も発生する可能性があります：

* ランダム性のないデータ: 規則的なデータしか入力していない場合、特定のエッジケースを見逃す可能性があります

* 現実的なデータでのレイアウト確認不足: 実際に運用する際のデータでは、想定外の文字数や内容でレイアウト崩れが発生する

これらの課題を解決するために、自動でテストデータを生成するスクリプトを利用することで、効率的かつ効果的なテストを実現できます。

### テストデータ作成スクリプトの実装

以下は、Pythonを使ってMT形式のテストデータを生成するスクリプトです。

#### スクリプトの説明
このスクリプトでは、以下のライブラリを利用しています：

* factory_boy: テスト用データを柔軟に生成できるライブラリです
* Faker: ダミーデータを簡単に生成するライブラリで、日本語対応も可能です

以下にスクリプトを示します。

```python
import factory
from faker import Faker
from datetime import datetime, timedelta

# Fakerのインスタンスを作成
fake = Faker("ja_JP")  # 日本語データを生成

# テストデータのFactoryクラス
class EntryFactory(factory.Factory):
    class Meta:
        model = dict  # 出力形式は辞書

    title = factory.LazyAttribute(lambda _: fake.sentence(nb_words=5))  # ランダムなタイトル
    body = factory.LazyAttribute(lambda _: fake.text(max_nb_chars=500))  # ランダムな本文
    author = factory.LazyAttribute(lambda _: fake.name())  # ランダムな著者名
    categories = factory.LazyAttribute(lambda _: [fake.random_element(["ニュース", "技術", "ブログ"])])
    tags = factory.LazyAttribute(lambda _: ",".join(fake.words(nb=3)))  # ランダムなタグ（カンマ区切り）
    date = factory.LazyAttribute(lambda _: (datetime.now() - timedelta(days=fake.random_int(min=1, max=365))).strftime("%Y-%m-%d %H:%M:%S"))

# MT形式データを生成する関数
def generate_mt_format_data(num_entries, output_file):
    with open(output_file, "w", encoding="utf-8") as file:
        for _ in range(num_entries):
            entry = EntryFactory()

            # Movable Typeのインポート形式にフォーマット
            mt_entry = f"""\
TITLE: {entry['title']}
AUTHOR: {entry['author']}
DATE: {entry['date']}
CATEGORY: {entry['categories'][0]}
TAGS: {entry['tags']}

-----
BODY:
{entry['body']}

-----
EXTENDED BODY:
{fake.text(max_nb_chars=200)}

--------
"""
            # ファイルに書き込み
            file.write(mt_entry)
    print(f"{num_entries}件のデータを {output_file} に保存しました。")

# 実行
if __name__ == "__main__":
    output_file = "mt_test_data.txt"  # 出力ファイル名
    generate_mt_format_data(10, output_file)  # 10件のデータを生成して保存
```

## スクリプトのポイント

1. ランダムで多様なデータを生成
タイトル、本文、タグ、著者名など、すべてランダムなデータを生成します。ただし、カテゴリは「ニュース」「技術」「ブログ」の中から選択するようにして、現実に近くなるよう調整しています。

2. Movable Type形式のデータとして保存
このスクリプトでは、MT形式のインポートデータを直接生成するため、そのままMTに取り込むことが可能です。

3. fakerを使用している利点
`fake.address()` で住所を、`fake.email()` でメールアドレスを生成するなど、カスタムフィールドで現実的なデータにも対応できます。

## テストデータをもっとリアルに

今回のスクリプトでは、時間の都合上、Fakerを使ったデータ生成を中心にしていますが、最近流行りの生成AIを活用すれば、もっとリアルなデータを生成することができます。

たとえば、以下のような改善が可能です：

* タイトルや本文をAIに生成させる
GPTモデルを使うことで、人が書いたようなリアルなニュース記事やブログ風の内容を自動生成できます。

* 画像データを生成
画像生成AI（例：DALL·EやStable Diffusion）を使って、それっぽい画像を生成し、フィールドに割り当てることも可能です。

* テストケースの多様化
長すぎるタイトルや、特定のキーワードを含む記事を生成して、特定のエッジケースをテストできます。

## まとめ
MTのテストデータを自動生成することで、以下のメリットを得ることができます：

* テスト作業の効率化
* 実際の運用に近いデータを使ったテストの実現
* 手作業での入力ミスやデータ不足の回避

また、生成AIを活用すれば、より現実的なデータを簡単に生成でき、テストの精度をさらに向上させることが可能です。
みなさんもぜひ試してみてください！