1. はじめに
AtCoderやPaizaのプログラミング課題で標準入力からデータを入力させられることが多いです。
Pythonの場合、
input()
を用いて値を受け取る必要があるので、自分の環境でデバッグする際に少々厄介だと思っていました。 テストケースが複数与えられた場合も入力の手間がかかりますし…
そこで、pytestを用いて一度に複数のテストケースを標準入力から入力してデバッグが行えるようなコードを考えてみたので記しておきます。
結論から先に記すとこのように、提出したいコードのままエディタで製作できますし、ブレークポイントを設定してのデバッグも可能です。
2. 環境
- エディタ:VScode
- 言語:Python
VScodeでのPythonの環境構築については省きますが、pytestを用いるので
pip install pytest
でインストールを行います。仮想環境を用いる場合は適宜調整してください。
VScodeでのpytestの利用に関しては、以下のサイトが参考になりました。
3. ソース
例えば、次のようなディレクトリ構成にします。
repo/
├── src
│ ├── input/
│ │ ├── input1.txt
│ │ ├── input2.txt
│ │ ~~~
│ ├── output/
│ │ ├── output1.txt
│ │ ├── output2.txt
│ │ ~~~
│ ├── main.py
│ └── test_main.py
-
input
: テストケース(入力)をテキストで記述 -
output
: 期待される出力を記述 -
main.py
: コーディング課題を記述する。 -
test_main.py
: テストケースを呼び出し、テストを行う。
以降Welcome to AtCoder
の課題を解くことを例に挙げて記述します。
input#.txt
とoutput#.txt
それぞれ、次の通りにします。
1
2 3
test
6 test
※テストケース2以降の場合も同様
main.py
def main():
# 関数やスクリプトを記述
a = int(input())
b, c = map(int, input().split())
s = input()
print("{} {}".format(a+b+c, s))
if __name__ == '__main__':
main()
test_main.py
main.py
のmain
関数を呼び出してテキストで保存したテストケースを読み取り、標準入力として与えます。
from main import *
import pytest
import io
@pytest.mark.parametrize(('fileNo'), [1, 2,]) #適応したいテストケースの番号をリストとして与える
def test_case(capsys, monkeypatch, fileNo):
inputs, outputs = load_data(fileNo)
monkeypatch.setattr('sys.stdin', io.StringIO(inputs)) #標準入力にファイルの内容をセット
main()
results, _ = capsys.readouterr()
assert results == outputs + "\n" #出力が答えと一致するか検証
def load_data(fileNo):
inputFile = F"src/input/input{fileNo}.txt"
outputFile = F"src/output/output{fileNo}.txt"
with open(inputFile, "r") as f:
inputs = f.read()
with open(outputFile, "r") as f:
outputs = f.read()
return inputs, outputs
4. 実行
VScodeでのテスト
バッジからpytestを実行すると、テストケースごとの結果得られます。その他デバッグも可能です。
5. まとめ
正直に言うと、私は競技プログラミングは超苦手なのでデバッグできるようになって良かったです。
私のgithub上に本記事で紹介したのと同様のものを挙げています。
ココではdevcontainerを用いて諸々が動作する開発環境を構築することができます。