AtCoderで自動サンプルテストケース&手入力値テスト実行 with VS Code

# はじめに
今までAtCoderはPython × Jupyter Labでやっていました。
今回、新しくVS Codeを使ってみたいということと、今までサンプルテストケースの実行が毎回手間だったことがあり、ググってみたらいい方法があったので残しておきます！

今回のゴールは以下の操作ができるようになることです。
1. VS Code上で```Ctrl + Shift + B```でサンプルテストケースでのテストを自動実行
2. VS Code上で```F5```で手入力値でのテスト実行

# 環境
* Ubuntu 18.04 LTS
* VS Code 1.42.1
* Python 3.7.1

今回Ubuntuで構築していますが、使っているのはシェルスクリプトとVS CodeなのでMacは勿論、WindowsでもWindows Subsystem for Linuxが入ってれば大丈夫…なはず？
※動作確認はしていないです！
####[2020/05/28更新]
Windows10で実践した記事が出てました！
[Python と VSCode で競プロ - 標準入力の簡易化とサンプルケース判定の自動化 -](https://qiita.com/ajim/items/4d350710ba70056f5f6f#_reference-43840d611e79ea0760cc)

# 参考にしたサイト
それぞれからつまみ食いさせて頂いた感じです。
大変参考になりました。ありがとうございます！
[Visual Studio Codeで競プロ環境構築(実践編)](https://qiita.com/AokabiC/items/af685bfd205dda44ec45)
[VSCodeでの競プロ向けPython環境をWindowsで作る](https://qiita.com/yoyomion/items/03e8e65fbd8a3d96d9e7)
[[GitHub]online-judge-tools](https://github.com/kmyk/online-judge-tools)

# フォルダー構成
AtCoderというディレクトリを切ってそこに環境構築しています。
コンテストの問題は{コンテスト名}\_{問題名}.pyというファイル名でproblemsディレクトリに全部突っ込みます。
ファイル名の{コンテスト名}部分は、AtCoderのコンテストページのURLと同じでないと動作しないので注意して下さい。
```https://atcoder.jp/contests/{コンテスト名}```
ファイル名例：
　AtCoder Beginner Contest 158のA問題
　(URL:https://atcoder.jp/contests/abc158/tasks/abc158_a)
　　→abc158_a.py
　日立製作所 社会システム事業部 プログラミングコンテスト2020のC問題
　(URL:https://atcoder.jp/contests/hitachi2020/tasks/hitachi2020_c)
　　→hitachi2020_c.py

```shell

AtCoder
├── cptest.sh #今回メインとなるシェルスクリプト
│
├── input.txt #ゴール2の手入力の値を入れるファイル
│
├── problems #コンテストの問題を格納するディレクトリ 
│
├── test #コンテストのサンプルケースを格納するディレクトリ
│
└── .vscode #VS Codeの設定ファイルを格納するディレクトリ
    ├── launch.json #ゴール2の設定ファイル
    └── tasks.json #ゴール1の設定ファイル
```

# online-judge-toolsのインストールとログイン
AtCoderのコンテストサイトから問題のサンプルテストケースをスクレイプして自動で実行してくれるめちゃくちゃ便利なツールです。
※他の主要オンラインコンテストにも対応しています。詳細は[GitHub](https://github.com/kmyk/online-judge-tools"Online Judge Tools")をご覧下さい。

pipでインストールします。

```bash:bash

$ pip install online-judge-tools
```

インストール完了後、ツールを使うためにAtCoderアカウントでログインする必要があります。
以下コマンドでログインします。
※{ユーザー名}と{パスワード}はご自分のに置き換えて下さい。

```bash:bash

$ oj login -u {ユーザー名} -p {パスワード} "https://atcoder.jp/"
```

以下でログインチェックが出来ます。

```bash:bash

oj login --check "https://atcoder.jp/"
```

# cptest.sh
ログインが完了している状態で、```cptest.sh abc158_a```のように拡張子(.py)無しの問題のファイル名を引数にして実行すると、サンプルテストケースでのテストを自動実行してくれるシェルスクリプトです。が、VS Codeの```Ctrl + Shift + B```に割り当てるので、ターミナルに打ち込んで実行することはありません。

```shell:cptest.sh

#!/bin/bash

problem_name=$1
test_dir=test/${problem_name}
base_url=${problem_name%_*}

# make test directory
if [ ! -e ${test_dir} ]; then
    oj dl -d test/${problem_name} https://atcoder.jp/contests/${base_url}/tasks/${problem_name//-/_}
fi

oj test -c "python3 problems/${problem_name}.py" -d test/${problem_name}
```

```oj dl -d test~```の部分でコンテスト問題のサンプルテストケースの情報をtestディレクトリ内にダウンロードして、```oj test -c~```の部分でダウンロードしたテストケースを使ってテストします。
####[2020/07/28更新]
M-SOLUTIONSプロコンオープン2020のコンテストで動作しなかったので、少し修正を加えました。
URLのコンテスト名がm-solutions2020で、問題名がm_solutions2020_aの形となっていたので、ファイル名をm-solutions2020_a.pyとしてproblem_name変数の-を_に置換するようにしました。

```shell:cptest.sh
# before
https://atcoder.jp/contests/${base_url}/tasks/${problem_name}

# after
https://atcoder.jp/contests/${base_url}/tasks/${problem_name//-/_}
```

# VS Codeでの設定
### input.txt
手入力でのテスト実行の入力値を入れるテキストファイルになります。
ターミナルから```python abc158_a.py < input.txt```という形で使えます。が、```F5```に割り当てるので、ターミナルから実行することはありません。

```text:input.txt
(標準入力として渡したい内容を記述)
```

### task.json
サンプルテストケースでのテスト実行を```Ctrl + Shift + B```に割り当てる為の設定ファイルです。
.pyファイルを開いている状態で```Ctrl + Shift + B```を押してビルドタスクを構成して以下の通りに```task.json```を作成して下さい。

```json:task.json
{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "test_atcoder_sample",
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "type": "shell",
            "command": "${workspaceFolder}/cptest.sh",
            "args": [
                "${fileBasenameNoExtension}"
            ]
        }
    ]
}
```

### launch.json
```F5```でVS Codeのデバッガを実行する為の設定ファイルになります。
デバッグしたい.pyファイルを開いている時に```F5```を押せば、input.txtの内容を入力として受け取って.pyファイルを実行します。

launch.jsonはVS Codeで```Ctrl + Shift + D```か```F5```を押してデバッグモードにして、左上の歯車をクリックすれば表示出来ます。初めて設定する場合は、左側に「新しくlaunch.jsonファイルを作成する」的なのが出てくる(はずな)ので、Pythonファイル用に新しく作って下さい。

```json:launch.json
{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python: Current File",
            "type": "python",
            "request": "launch",
            "program": "${file}",
            "console": "integratedTerminal",
            "args": [
                "<",
                "input.txt"
            ]
        }
    ]
}
```

# テスト実行(abc158_a.pyの例)
上記設定を済ませれば、後はコードを書いて実行するだけです。
[ABC158のA問題](https://atcoder.jp/contests/abc158/tasks/abc158_a"A - Station and Bus")を例にそれぞれ実行してみます。
### [ゴール1]サンプルテストケースでのテスト実行
以下が```Ctrl + Shift + B```を実行した時のキャプチャになります。

![Screenshot from 2020-03-15 01-43-35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542930/8b5ccb16-ea0f-cca3-7fa5-c09a0c511671.png)
サンプルテストケースは全部ACしていますね。
### [ゴール2]手入力でのテスト実行
手入力でのテストも実施してみます。"AAA"という入力でテストしてみましょう。
input.txtに"AAA"と記載して保存したら、abc158_a.pyに戻って```F5```を押します。

```text:input.txt
AAA
```

"No"と結果が返ってきます。

#最後に
サンプルテストケースでのテストが自動化されるのは勿論ですが、input.txtで入力値が設定できるのも非常に快適度が上がります。特に入力値がリストだったり、*ｉ*回繰り返されるタイプの時に力を発揮します。
今回使ったonline-judge-toolsは、サンプルテスト以外でも提出の自動化等もできるみたいなので色々とやってみるのもいいかもしれません。
また、これを機にVS Codeデビューしましたが、まだまだ使いこなせていない機能がたくさんありそうなので、引き続き精進していきたいと思います！！