🔖

【Streamlit】Streamlitのテスト用モジュール入門

2024/12/16に公開

こんにちは。データエンジニアの山口歩夢です!

Streamlitにはたくさんの便利な関数が用意されていて、簡単にアプリケーションの開発ができますが、AppTestというテスト用にも便利なモジュールも用意されています。
こちらを活用することで、テストコードを非常に手軽に書くことができます。

テストコードを書くことで、ユーザーがウィジェットに入力した内容や出力値などを検証することができ、アプリケーションの保守性を高めることができます。
本記事ではpytestAppTestを組み合わせてテストを行いますが、pytestに限らず、様々なテストツールを使用できるようです。

https://docs.streamlit.io/develop/concepts/app-testing/get-started

今回は、「Streamlit入門 Pythonで学ぶデータ可視化&アプリ開発ガイド」で紹介している以下のようなアプリケーションのテストコードを作成してみようと思います!

image.png

細かくテストするというよりも、サイドバーのセレクトボックスやタイトル名、データフレームの数などをサクッと簡単にテストしてみます。

実装

それでは早速実装していきます!

ptytestのインストール

まずは、pytestをインストールします。
pip installなどでインストールすることができます。

$ pip install pytest

ファイルの用意

以下のような構成でディレクトリを用意します。
テストを書くファイルは、先頭または末尾にtestと付くように命名します。
本記事では、test_app.pyとします。

├── streamlit_app.py
└── tests/
    └── test_app.py

テストコードの用意

それでは、テストコードを用意していきます。
アプリケーションの以下の要素に対してテストを行っていきます。

サイドバー

  • st.titleのテキスト
  • st.selectbox
    • labelのテキスト
    • 初期入力値

メインエリア

  • st.headerのテキスト
  • st.dataframeで出力しているデータフレームの数

結論、以下のようなテストコードを用意しました!
テスト用の関数にもtest_appというように、先頭にtestが付くように命名します。

# test_app.pyファイル
from streamlit.testing.v1 import AppTest


def test_app():
    # アプリをテストする準備
    at = AppTest.from_file("streamlit_app.py").run()

    # サイドバーのタイトルと選択ボックスのラベルを確認
    assert "製品の選択" in at.sidebar.title[0].value
    # selectbox ラベルの確認
    assert at.sidebar.selectbox[0].label == "製品大分類の選択"
    at.sidebar.selectbox[0].set_value("電子機器").run()  # 大分類
    assert at.sidebar.selectbox[1].label == "製品中分類の選択"
    at.sidebar.selectbox[1].set_value("コンピューター").run()  # 中分類
    assert at.sidebar.selectbox[2].label == "製品小分類の選択"
    at.sidebar.selectbox[2].set_value("ノートパソコン").run()  # 小分類

    assert "製品データ可視化ダッシュボード" in at.header[0].value

    # データフレームの確認
    assert len(at.dataframe) == 1

以下のようなコマンドを実行することで、上記のテストコードを使用してテストを行うことができます。

$ pytest test_app.py

テスト結果は以下のように表示されました。
1 passedと出力されているので、テストコード内の関数がテストを通過していることが分かります。
image.png

テストコードの解説

ライブラリのインポート

StreamlitにはAppTestというテストコードを書くためのライブラリが用意されています。
以下のようにimportをして、こちらのライブラリを使用してテストコードを書いていきます。

from streamlit.testing.v1 import AppTest

AppTestインスタンス初期化&アプリの実行

AppTestを使用してテストを行う場合、最初にAppTestのインスタンスを初期化する必要があります。
ドキュメントを読む限り、AppTest.form_file()を使用して、インスタンスを初期化することが推奨されていました。
こちらを使用すると、テスト対象のPythonスクリプト(streamlit_app.py)を指定して、テストを行うことができます。

そして、末尾にrun()をつけることで、アプリケーションの実行を再現します。

at = AppTest.from_file("streamlit_app.py").run()

st.titleのテキスト

サイドバーにst.titleで出力しているタイトルのテキストは以下のようにテストをします。

アプリケーション内で最初のst.titleをテストするため、at.slidebar.title[0].valueと書いています。

もし、他にもst.titleで出力しているタイトルがあれば、
at.sidebar.title[1].valueat.sidebar.title[2].value...のように、title[n]のnの数値を増やしていきます。

assert "製品の選択" in at.sidebar.title[0].value

st.selectboxのラベル・初期入力値

サイドバーのセレクトボックスのラベルや初期入力値は、以下のようにテストをします。

出力しているセレクトボックスが複数あるため、
at.sidebar.selectbox[1].valueat.sidebar.selectbox[2].value...と`selectbox[n]のnの値が増えていっています。

assert at.sidebar.selectbox[0].label == "製品大分類の選択"
at.sidebar.selectbox[0].set_value("電子機器").run()  # 大分類
assert at.sidebar.selectbox[1].label == "製品中分類の選択"
at.sidebar.selectbox[1].set_value("コンピューター").run()  # 中分類
assert at.sidebar.selectbox[2].label == "製品小分類の選択"
at.sidebar.selectbox[2].set_value("ノートパソコン").run()  # 小分類

st.headerのテキスト

メインエリアのst.headerは以下のようにテストをします。

assert "製品データ可視化ダッシュボード" in at.header[0].value

st.dataframeのデータフレームの出力数

st.dataframeで出力しているデータフレームの数は以下のようにテストしました。

assert len(at.dataframe) == 1

その他

st.file_uploaderなどは、まだテスト用の関数が用意されておらず、順次追加予定の様子です。

https://docs.streamlit.io/develop/concepts/app-testing/cheat-sheet

まとめ

Streamlitには、テスト用の関数が多く用意されていることが分かりました。
細かくテストをするというよりも、シンプル且つ高速にテストをするのに便利だなといった印象でした。

公式で用意されている、以下のチートシートを見ながらテストコードを書くのがおすすめです!

https://docs.streamlit.io/develop/concepts/app-testing/cheat-sheet

宣伝

12/6に「Streamlit入門 Pythonで学ぶデータ可視化&アプリ開発ガイド」という技術書を発売致しました。
Streamlitの基礎から、Streamlitを活用したアプリケーションの開発について、300ページにわたって解説させていただきました!

image.png

https://www.amazon.co.jp/Streamlit入門-Pythonで学ぶデータ可視化&アプリ開発ガイド-技術の泉シリーズ-山口-歩夢/dp/4295603511?source=ps-sl-shoppingads-lpcontext&ref_=fplfs&ref_=fplfs&psc=1&smid=AN1VRQENFRJN5

Discussion