PythonのプロジェクトをTeamcityで自動テストする

## 目的

Pythonの自動テスト環境を構築する。

## 環境

* TeamCity Professional 2019.2.2 (build 71923)
    * dockerコンテナubuntuバージョン
* Python 3.7.6
* Poetry 1.0.5

## 概要

以下の条件であればTeamcityでなくても問題はない。
TeamcityのビルドエージェントはDockerコンテナで環境がわけられていい。

* Pythonの実行環境がある
* 単体テストの全実行ができる
* フォーマッタを全ソースに自動適用できる
* 静的コード解析を全ソースに自動適用できる

## Pythonの実行環境

### Python用ビルドエージェントコンテナ

MinimalのエージェントコンテナをベースにPythonの環境を構築していく。
ｐyenvを使うとコードが短くなるしanacondaなど実装系とも共通化できるので利用した。

```dockerfile:Dockerfile
FROM jetbrains/teamcity-minimal-agent:latest

LABEL maintainer="YAMAGAMI Satoshi"

# python preparation start

ENV HOME /root
ENV PYENV_ROOT $HOME/.pyenv
ENV PATH $PYENV_ROOT/bin:$PYENV_ROOT/shims:$HOME/.local/bin:$PATH
ENV DEBIAN_FRONTEND=noninteractive
RUN apt update -y && \
    apt upgrade -y 

RUN apt install -y make build-essential libssl-dev zlib1g-dev libbz2-dev \
libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev \
xz-utils tk-dev libffi-dev liblzma-dev python-openssl git
 
    
# RUN curl https://pyenv.run | bash
RUN git clone https://github.com/yyuu/pyenv.git $HOME/.pyenv

#python $VERSIONをインストールしglobalでデフォルトのバージョンにセットする
ARG VERSION="3.7.6"
RUN pyenv install ${VERSION} && \
    pyenv global ${VERSION} && \
    pyenv rehash &&\
    eval "$(pyenv init -)" 

RUN pip install --upgrade pip 
    

# python preparation end
##################################
```

```yml:docker-compose.yml（抜粋）
version: '3'

services:
  ci-agent-python:
    build: ./ci/ci-agent/python
    environment: 
      - SERVER_URL=ci:8111
      - AGENT_NAME=python
    ports:
      - 9092:9090
    volumes:
      - ./ci/agent-python/conf:/data/teamcity_agent/conf
```
---

### 依存関係のインストール

poetryを使っているので以下のようになる。
こういうコマンドはちゃちくてもコードとしてGitで管理したほうがいい。

コンテナではpipまで入っているのでpoetryのインストールから。

```sh:scripts/install.sh
#!/usr/bin/env bash

pip install --user poetry
poetry --version
poetry config virtualenvs.in-project true --local
poetry install --no-root
```

## 単体テストの全実行

合わせてカバレッジも取得する。
`poetry shell`コマンドだとactivateしてスクリプトが終わってしまうため手動で`$PATH`に追加

```sh:scripts/test.sh
#!/usr/bin/env bash

export PATH=`poetry env info --path`/bin:$PATH
`which python` -m pytest --cov=sample_tdd --cov-report=html --html=reports/test/results.html --self-contained-html
```

## フォーマッタを全ソースに自動適用

使用しているフォーマッタ(autopep8)がファイル単位なのでfindを使って対応。
.venvをプロジェクト配下にしているので除外。

```sh:scripts/format.sh
#!/usr/bin/env bash

export PATH=`poetry env info --path`/bin:$PATH
find . -type d -name .venv -prune -o -type f -name "*.py" -exec `which python` -m autopep8 --in-place {} \;
```

## 静的コード解析を全ソースに自動適用

特になんの変哲もない。

```sh:scripts/inspect_code.sh
#!/usr/bin/env bash

export PATH=`poetry env info --path`/bin:$PATH
`which python` -m flake8
```

## 自動化

プロジェクトを作成してソースのVCSを設定したらビルドステップを設定する。
シェルスクリプトがあると自動で候補にあげてくれるので、必要なものにチェックする。
順番を並び替えたら実行する。
テストレポートを見るために、成果物(Artifacts)を指定している。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166036/f8c64947-87a4-810d-9327-8279a418aa76.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166036/adb9cdc5-aa50-2dc7-2b4e-5d785064205a.png)

パイプライン化するにはテスト結果やコード解析の結果を見てDockerコンテナのデプロイに繋いでいくのだけれど、今回はテスト自動化ということでここまで。

最初`.venv`をプロジェクト配下にしない構成でやっていたのでコードフォーマットと静的コード解析が16mくらい起きてました。
みんなも気をつけようね！

いじょ。
---
CI、python関連で以下を書いてますので興味があれば。
[Python開発環境](https://qiita.com/syamagami666/items/beecb054214f2ec5aadd)
[DockerコンテナのTeamCityを使ってみた](https://qiita.com/syamagami666/items/0adaa5c1456f6a6ea2ef)
[TeamCityビルドエージェントコンテナにJDKを追加する](https://qiita.com/syamagami666/items/342928df285678149819)