こんにちは、TaKO8Kiです。
RustでDB操作を伴う関数をテストしたいなーと考えていた時にいい感じのライブラリが見当たらなかったので作ってみました。
DB操作を伴う関数をテストする時は大きく分けて以下の2パターンあると思うのですが、今回作ったのは前者の方に焦点を当てたライブラリです。
- テスト用のDBを用意して、そこに実際にテストデータを用意してテストを行う。
- database poolなどモックできるような実装にすることで、実際にはsqlの実行を行わずにテストを行う。
使い方
このライブラリはsqlxをベースにしており、async runtimeはtokioとasync-stdに対応しています。
インストールする際は下記のようにします。
async-std
# Cargo.toml
[dependencies]
testfixtures = "0.1"
sqlx = "0.3"
chrono = "0.4.11"
tokio
[dependencies]
testfixtures = { version = "0.1", default-features = false, features = [ "runtime-tokio" ] }
sqlx = { version = "0.3", default-features = false, features = [ "runtime-tokio", "macros" ] }
chrono = "0.4.11"
実際に使う時にはまず、下記のようなfixturesファイルを作ります。この際、YAMLファイルの名前をテーブル名と対応させます。
# fixtures/todos.yml
- id: 1
description: buy a new camera
done: true
progress: 10.5
created_at: 2020/01/01 01:01:01
- id: 2
description: meeting
done: false
progress: 30.0
created_at: 2020/01/01 02:02:02
その後、それぞれのテストの中でfixtureをロードします。
#[cfg(test)]
mod tests {
use chrono::Utc;
use sqlx::MySqlPool;
use std::env;
use testfixtures::MySqlLoader;
#[async_std::test]
async fn test_something() -> anyhow::Result<()> {
let pool = MySqlPool::new(&env::var("DATABASE_URL")?).await?;
let loader = MySqlLoader::new(|cfg| {
cfg.location(Utc);
cfg.database(pool);
cfg.skip_test_database_check();
cfg.paths(vec!["fixtures/todos.yml"]);
})
.await?;
// fixturesをロードする
loader.load().await.unwrap();
// テスト実行
Ok(())
}
}
さらに詳しくはREADMEを見てください!
現状できること
このライブラリはgo-testfixtures/testfixturesを参考に作ったものなのですが、それと比較すると、まずDBに関しては、現状はMySQLのみに対応しており、現在、PostgreSQLに対応させようとしているところです。さっと実装できそうであればSQLiteにも対応させたいと思います。
また、オプションに関しては、下記のような実装ステータスです。
オプション | 実装済みかどうか? |
---|---|
fixtureファイルをfile pathを指定して読み込む | true |
fixtureファイルをディレクトリ単位で読み込む | true |
上記両方を混在させてロードする | true |
database名がテスト用か確認する | true |
locationを指定する(現状意味ないけど) | true |
fixtureファイル内でtemplateを使えるようにする(参考) | false |
割といい感じに出来上がった気がするので、もしよかったら使ってみてください!
PR、starも待ってます!