[Tips] sam-cliのbuildコマンドでインストールした外部パッケージをユニットテストで使おうとしたら使えなかった話

2019.08.16

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんばんは、CX事業本部の夏目です。

sam-cliのbuildコマンドを使って依存ライブラリのインストールする際の挙動で気づいたことを共有します。

動かないテスト

sam-cliのbuildコマンドではSAMのテンプレートを読み取って依存ライブラリを一通りインストールしてくれる機能があります。

今回私はPythonで画像を編集したくて、Pillowというパッケージをインストールしようとしました。

$ sam build -t sam.yml

mac上でユニットテストをするために、sam build-uオプション(コンテナ内で外部パッケージをインストールする)なしで実行しました。

しかし、依存ライブラリをインストールしたのでユニットテストを実行するとエラーで止まってしまいました。

$ PYTHONPATH=.aws-sam/build/AnalyzeFunction/ \
> python -m pytest tests/unit/AnalyzeFunction/test_index.py 
======================================================================================== test session starts ========================================================================================
platform darwin -- Python 3.7.2, pytest-5.0.1, py-1.8.0, pluggy-0.12.0 -- /Users/natsume.yuta/workspace/classmethod/ccommit/sam-build-test/.venv/bin/python
cachedir: .pytest_cache
rootdir: /Users/natsume.yuta/workspace/classmethod/ccommit/sam-build-test, inifile: setup.cfg
collected 0 items / 1 errors                                                                                                                                                                        

============================================================================================== ERRORS ===============================================================================================
_____________________________________________________________________ ERROR collecting tests/unit/AnalyzeFunction/test_index.py _____________________________________________________________________
ImportError while importing test module '/Users/natsume.yuta/workspace/classmethod/ccommit/sam-build-test/tests/unit/AnalyzeFunction/test_index.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/Users/natsume.yuta/workspace/classmethod/ccommit/sam-build-test/tests/unit/PutS3EventFunction/test_index.py:1: in <module>
    ???
.aws-sam/build/AnalyzeFunction/index.py:3: in <module>
    from image_analyzer import main
.aws-sam/build/AnalyzeFunction/image_analyzer.py:11: in <module>
    from PIL import Image
.aws-sam/build/AnalyzeFunction/PIL/Image.py:95: in <module>
    from . import _imaging as core
E   ImportError: cannot import name '_imaging' from 'PIL' (/Users/natsume.yuta/workspace/classmethod/ccommit/sam-build-test/.aws-sam/build/AnalyzeFunction/PIL/__init__.py)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
====================================================================================== 1 error in 0.22 seconds ======================================================================================

何故かPillowのimportで失敗してしまうようです。 それもPillow内部での参照で。

原因

この原因は、実際にインストールされているものを見るとわかりました。

Linux用のshared objectファイルが作成されています。

どうやら、sam-cliのbuildでは-uオプションをつけなくてもLinux用のビルドを行うようです。

まとめ

いかがでしょうか? sam-cliの意外な落とし穴でした。 自分はこれに気づくのに2時間ほどかかってしまいました。

ユニットテストの際には、sam buildを使わずに別の手段で外部パッケージをインストールしましょう。