Qiita に書いた Rust の記事のコードブロックを rustdoc でテストする

  • 16
    Like
  • 0
    Comment
More than 1 year has passed since last update.

TL;DR: これを実行する: rustdoc --test <(curl -s ${記事URL}.md | sed 's|^|//! |')


rustdoc は Markdown のコードブロック内の Rust コード片をテストできる。また Qiita の記事の Markdown は URL の末尾に .md を付けると取得できる。

とすると、 Qiita の記事中の Rust コード片を rustdoc でテストすることもできる。試してみよう。

test0
use std::char;
let a = char::from_u32(0x61);
assert_eq!(a, Some('a'));
test1
fn none() -> Option<()> { None }
assert_eq!(none(), None);

上にいくつか Rust のコードブロックを書いてみた。この記事中のコードをテストするには次のコマンドを実行する:

rustdoc --test <(curl -s http://qiita.com/uasi/items/bbfeaa4269a9de44e81e.md | sed 's|^|//! |')

すると以下の出力が得られる:

running 2 tests
test _1 ... ok
test _0 ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured

テストが通った :v: どんどんテストして誤りのない記事を書こう。

テストに対応した Markdown の書き方について

基本的には ```rust``` でコードを囲むだけでいい。 Rust 以外の言語のコードブロックも含めるなら言語名を明示する。またコードブロックの前後には最低1行の空行が必要:

テストに対応した Markdown の書き方について

↑サンプルの Markdown を直に書きたかったのだが問題があって画像で貼った。 ``` を文中に含む整形済みテキストを書くと rustdoc が誤認識するようだ。

.md つき URL が返す Markdown は先頭に記事タイトル行が追加されることに注意。もし本文の1行目からコードブロックを書くとタイトルとくっついてしまい、そのコードブロックは実行されなくなる。

コマンドの解説

テストを実行するコマンドを解説する。

rustdoc --test <(curl -s http://qiita.com/uasi/items/bbfeaa4269a9de44e81e.md | sed 's|^|//! |')

rustdoc --test は引数にファイルパスを受け取り、拡張子からファイル形式を判断してテストを実行する。 rustdoc v1.0.0 では標準入力からファイルを読むことはできない:

cat foo.md | rustdoc --test -  # これはだめ

そこでプロセス置換記法 <(command...) を使う。コマンドの標準出力結果をファイル(のようなもの)として扱うことができる。

curl -s http://...md で Qiita の記事 の Markdown ソースを標準出力に流す。 -s オプションは curl のプログレスメータを非表示にするため。

rustdoc はファイルの拡張子からファイル形式を判断すると書いたが、プロセス置換でファイルを流し込むと拡張子は分からない。このとき rustdoc は入力が Rust のソースだと判断する。つまり直接 Markdown ソースを流し込むことはできない。

そこで Markdown ソースを sed 's|^|//! |' で処理し、ソースの各行に Rust のドキュメントコメントマーカー //! を追加する。こうするとソースは Rust のコードとして正しいものになる。

まとめると、 <(curl ... | sed ...) で記事の Markdown ソースを取得し、 Rust ソースになるよう整形してファイルっぽく扱うということ。これを rustdoc --test の引数に渡すことでテストを実行できる。