私が歌川です

@utgwkk が書いている

旧居を退去

昨日退去立ち会いをやった。歴史的経緯によって管理会社の人も自分も原状があいまいすぎた。6年も住んだら壁紙代はチャラになる。

敷金から賃貸契約時に定めたクリーニング代を差し引いた額が全部返ってくるので、実質的に満額返還ということになる。今更気になってクリーニング代について調べてみた。クリーニング特約というものがあるらしい。こちらとしては、請求されすぎなければなんでもよい気がする。

Q16 賃貸借契約にクリーニング特約が付いていたために、契約が終了して退去する際に一定の金 額を敷金から差し引かれました。このような特約は有効ですか。

A クリーニング特約については①賃借人が負担すべき内容・範囲が示されているか、②本来 賃借人負担とならない通常損耗分についても負担させるという趣旨及び負担することに なる通常損耗の具体的範囲が明記されているか或いは口頭で説明されているか、③費用と して妥当か等の点から有効・無効が判断されます。 https://www.mlit.go.jp/common/001005064.pdf

空っぽになった旧居で手を叩くと、音がやけに反響した。学生時代をまるまる過ごした家なので安くて狭くて不便でも思い出ぐらいはある。ユニットバスを破壊した思い出とか……。

引っ越してから買ったもの

引っ越すにあたっていろいろ買った。

冷蔵庫

www.muji.com

無印良品の冷蔵庫を買った。基本的に水とコーラぐらいしか冷やさないのでなんでもいいと思うけど、下側が冷凍室なのが気に入っている。

ドラム式洗濯機

部屋の見学をしたときは、これはドラム式洗濯機を置けるかは怪しいですね、と言われたのだけど無事に設置できた。洗濯から乾燥まで一気にやってくれるので楽。動作音や振動はそんなに気にならない。

プラズマクラスターの効果はよくわからない。

空気清浄機

加湿器を新しくするついでに加湿機能付きのものを買った。空気のきれい度ランプみたいなのが付いていて、旧居から持ってきた段ボール箱を開封すると赤くなっておもしろかった。

プラズマクラスターの効果はよくわからない。

ルンバ

ルンバの名前はパイモンにした。ちゃんと分かるようにテプラを貼ってある。名前付きの首輪みたいなマインドだと思う。

床の物を全部どかしておいたらルンバが勝手に掃除してくれて便利。たまにゴミ入れを掃除するとホコリが溜まっていてすごい。継続的に掃除してくれるのがいい。

メタルラック

床にモノを置くだけでは収納効率がよくない。大小あわせていくつか買った。組み立てがやや大変だけど確かに高さ方向のスペースをうまく使えるようになって便利。

カーペット

旧居から持ってきたラグやカーペットを新居の部屋に敷くとサイズがぜんぜん合わなかった。どうせなので新調することに。こたつを使うので、こたつと両立できるものを選んだ。

昇降机

flexispot.jp

部屋が広くなったので机が欲しいと思っていて、Flexispotの手動昇降机がよいらしいと教えてもらったので買った。これまではこたつで仕事していたので遥かにグレードアップした。組み立てが大変だった……。

終わりに

手取りを超える額の引き落しが控えているけど後悔はしていない。おかげでヨドバシポイントが10000ptを超えた。


今週のお題「買ってよかった2021」

よいレビューコメントを集めておきたい

弊社では他者評価を行うことになっているのだけれど、その際に他者評価対象の同僚のファインプレーをサクッと思い出せるようにしたい、と日頃から思っている。振り返りの文章で言及されていない内容だとなおよいと思う。

最高の実装ができてすごい!! の他にも、こういうレビューコメントで救われました、プロダクトの性質を見通すことができている!! といったことを伝えておきたい。評価シーズンになってから思い出すと時間がかかるので日頃からメモしておきたい、と他者評価の入力を終えてから思った。

GitHubだとPRのレビューコメントに対するpermalinkが取れるので、それをスプレッドシートとかに記録しておくのが手軽だろうか。いいと思ってみんなにも知ってもらいたいなら日頃からそういう表明をしておくとよさそう。ファインプレーのpermalinkならなんでもいいはずなので、レビューコメントに限らずPRのdiffとか、issueのコメントとか、そういうのも記録しておくとよいのではないか。

『「集合と位相」をなぜ学ぶのか』を読んだ

熱伝導方程式を解くためにフーリエ級数の理論が考案されて、ところで積分とは何か、実数とは、集合とは……というふうに、先人の議論を追って、集合・位相が数学における共通語になった経緯を教えてくれる本だった。

証明はぬるっと流す感じで読んだ。学生時代も微分積分学の講義の証明をよく噛み砕けなくて丸暗記してから試験に臨んだのだった……。

最新グッズ情報

あのTシャツがついに出ました。トリブンを0円にしたらめっちゃ安くてすごすぎる。

suzuri.jp

あわせて読みたい

blog.utgw.net

pytestプラグインだってテストされたい

はじめに

これはPython Advent Calendar (3) 17日目の記事です。

pytestプラグインのテストについてお話しします。プラグインの実装方法については今回は触れないので、気になった人はWriting plugins — pytest documentationを読んでみてください。

pytestについて

pytestは、Pythonのテストフレームワークです。Python標準ライブラリのunittestに比べて、assert 文を使って簡潔にテストケースを記述できる*1、fixtureなどを再利用する仕組みがある、たくさんのプラグインが作られているのが特徴です。

プラグインだってテストされたい

みなさまも便利なプラグインを使ってテストを快適に書きたいと思っているところだとは思いますが、ここで1つ疑問が出てきます。プラグインの実装が意図した通りであることは、どうやって確かめればよいでしょうか? プラグインが実は壊れていた、ということになると良くないですね。

一番手っ取り早いのはテストでしょう。pytestには、実装したプラグインに対するテストを実装する仕組みが用意されています。この記事では、拙作のpytestプラグインであるpytest-github-actions-annotate-failuresを例に、pytestプラグインのテストの書き方について少しだけ解説します。

pytest-github-actions-annotate-failuresについては以前別の記事で取り上げたので、気になる方はそちらをご覧ください。

blog.utgw.net

pytestプラグインをテストする

以下のテストケースを例に解説します。

def test_annotation_fail(pytester, monkeypatch):
    pytester.makepyfile(
        """
        import pytest
        pytest_plugins = 'pytest_github_actions_annotate_failures'

        def test_fail():
            assert 0
        """
    )
    with monkeypatch.context() as m:
        m.setenv("GITHUB_ACTIONS", "true")
        result = pytester.runpytest_subprocess()

    result.stderr.fnmatch_lines(
        ["::error file=test_annotation_fail.py,line=5::test_fail*assert 0*",]
    )

テストファイルを生成する

pytester.makepyfile メソッドで、pytestプラグインを有効にしてテストを走らせる (=このテストファイルをもとにプラグインの挙動を確かめる) 対象のファイルを生成します。

先述した例だと、以下のようなファイルが test_annotation_fail.py という名前で一時ディレクトリに作成されます。解説のためにコメントを入れています。複数行の文字列リテラルを使ったぶん、先頭に空行が入っていることに注意しましょう。

# ここに空行が入る
import pytest
pytest_plugins = 'pytest_github_actions_annotate_failures'

def test_fail():
    assert 0

pytest_plugins は読み込むpytestプラグインを指定するための変数です。

環境変数を設定する

pytest-github-actions-annotate-failuresプラグインは、GITHUB_ACTIONS 環境変数が true という値であるときだけ動作します。この挙動を確かめるために、monkeypatch.setenv メソッドを使って、生成したテストファイル内でだけ GITHUB_ACTIONS 環境変数の値を書き換えます。

コンテキストマネージャを使うことで、書き換えた環境変数がテストファイルを実行するプロセスでのみ有効であるようにします。

テストファイルを走らせる

pytester.runpytest_subprocess メソッドを呼ぶことで、生成したテストファイルを走らせます。ここで走らせたテストの結果は、元のプラグインのテストには影響しません。このテストの結果を使って、プラグインが意図通りに動いているかどうかを確かめていきます。

アサーションを書く

pytest-github-actions-annotate-failuresプラグインは、テストが失敗したとき、失敗内容を特定の書式で標準エラー出力にprintします。したがって、標準エラー出力に特定のパターンに一致する文字列が書き出されていることを確認できればよさそうです。

result.stderr で標準エラー出力を表すオブジェクトが取得できるので、その fnmatch_lines メソッドを呼ぶことで確認できます。

できました

これでpytestプラグインの挙動を確認するテストが書けました。

pytestには他にもさまざまなfixtureが用意されています。興味がある人は公式ドキュメントをあたってみてください。

testdir fixtureについて

ここまで例として使ったテストコードは、pytest-github-actions-annotate-failuresプラグインのリポジトリにあります。

github.com

ところで、リポジトリのテストコードを見ると testdir というfixtureが使われていることに気づくと思います。testdir は古いfixtureで、2021/12/13現在では testdir ではなく pytester などのfixtureを使うことが推奨されています。pytesterpytest 6.2.0で追加されたfixtureです。

pytest-github-actions-annotate-failuresプラグインはPython 2.7もサポートしています。Python 2.7ではPytest 4.6.Xまでしか使うことができません*2。互換性のために古いfixtureを使い続けている状態です。

おわりに

Test2もそうであるように、テストフレームワークの側がテストプラグインのテスト (メタなテスト?) を書きやすいように設計されていると、プラグインを実装する側としてもありがたいです。

きちんとテストされたプラグインを使って、テストを安全かつ快適に書きたいですね。

*1:unittestの記法を使うこともできます

*2:Python 2.7 and 3.4 support — pytest documentation

ResizeObserverとCSS transformとreact-use-measure

前提として、ResizeObserver は、CSS transformによる要素サイズの変化を検知しない。CSSの transform 属性を動的に書き換えても ResizeObserver は検知してくれない。

Observations will not be triggered by CSS transforms.
Resize Observer

framer-motionというライブラリで transform 属性を書き換えて scale(...) の値を動的に書き換えるようなアニメーションをしつつ、その子要素でreact-use-measureuseMeasure フックを使って子要素のサイズを測定するときにハマった。

useMeasure フックは内部で ResizeObserver を使っているが、これとframer-motionによるアニメーションを組み合わせると、要素の大きさとしてアニメーション途中の値が採用されてしまう。欲しいのはアニメーション完了時 (transform: scale(1) になる) の大きさなので、これではうまくいかない。

困ったのでreact-use-measureの実装を読みにいったら、つい最近react-use-measureの新しいバージョンが出ており、その中でも目を引くcommitがあった。

github.com

useMeasure フックの引数に offsetSize というオプションが追加されていた。この値を true にすると、要素の大きさとして常に offsetWidth offsetHeight を採用するようになる。

要素の大きさについてMDNを参照すると、以下のように求めていたものであることが例示付きで書いてあった。

offsetWidth および offsetHeight は要素のレイアウトの幅と高さを返し、getBoundingClientRect() はレンダリングの幅と高さを返します。例として、要素に width: 100px;transform: scale(0.5); がある場合 getBoundingClientRect() は幅として 50 を返し、offsetWidth は 100 を返します。
要素の寸法の決定 - Web API | MDN

ということで、react-use-measureのバージョンを最新版にした上で offsetSize オプションを true に設定することで解決できた。

ところで今回の要件には入らなかったけど、CSS transformを動的に書き換える場合の要素の大きさの変化を検知するいい方法はあるのだろうか。要素の style 属性を書き換えるならMutationObserverを使えばなんとかできる?