2018年10月26日金曜日

paizaスキルチェックを攻略したい

paizaスキルチェックを攻略したい!

1.TDD覚えた!
2.何かプログラミングしたいなぁ...
3.そういえばpaizaにちょうど問題があるじゃん
4.とりあえず、TDDは置いといてpaizaってどんな問題があるんだろ?
5.やってみた
クリアできなかったTAT

悔しいから、クリアする方法を考える。

<考えたこと>
早さが足りなかった...
ただ早さのために、ソースコードの質は落としたくない
アルゴリズムを考える速度はあまり変わらない気がする
プロセスを見直すべきでは?
・そもそも、普段ブラウザ上でプログラミングしないじゃん
・ついでにTDDによる、小さなサイクルも取り入れたい

ということで、
今回の目標は
ローカル環境でプログラミングし、コピペで提出したい


ところで、ローカル環境でプログラミングするとき、paizaのブラウザ上で行うのと明確に違う部分が一つあります。
完成したプログラムがテストできない!
プログラミングの後半では、入出力のチェックが欠かせないけど、ローカル環境だと、テストできない。
テストケースは、問題に書いてあるけど、いちいち写してられない。

これは簡単に、テストケースをコピペできて、テストができるテストドライバが必要だなーってことでプログラミング。

ファイル構成
main.py - Paizaの課題を書くファイル
mini_test.py - TDD用のユニットテストを書くファイル
testTool.py - テストドライバを書くファイル
test_paiza.py - プログラムの完成を確認するテストを書くファイル
testcase.py - Paizaのテストケースをコピペするファイル
TODOLIST.txt ー 仕様や気になることをメモするファイル


このファイルをコピーして使うことを想定。
基本的に、main.pyとmini_test.py、testcase.txt、TODOLIST.txtは空のファイルで、ここに課題のプログラムを書く感じ。

test_paiza.pyにテストコードを書いて、テストに使うこまごまとした、インプットやアウトプットのメソッドはtestTool.pyにって感じで。
テストの成功判定にはPytestを使います。

まずは、paizaの出題形式を再現しないといけない。
paizaでは標準入力としてinput()の形でデータが流し込まれる。
さらに、その入力は1度ではなく複数回行われる。

例えば、こんな感じの割り算をして、商とあまりを答えさせるプログラムなら。
入力例
5
3
出力例
1
2
と、こんな感じ。pytestでテストを書くとなんとなくこんな感じになりそう。

>test_paiza.py
def test(capsys):
    testCase = ["5","3"]
    expected = "1\n2\n"
    test = main.program(input)
    test.start()
    out,err = capsys.readouterr()
    assert out == expected

なるほどなーと。
とりあえずinputとoutputいちいち手動で写してられないから何とかしないとね。
そもそも、ハードコーディングしているから、依存関係ぶっこ抜かないと。
先にハードコーディングのぶっこ抜きから。

inputMessage = "testCase,expected"
detabase = [(["5","3"],"1\n2\n"]),(["8","2"],"4\n0\n")]

@pytest.mark.parametrize(inputMessage,detabase)
def test(testCase,expected):
    test = main.program(input)
    test.start()
    out,err = capsys.readouterr()
    assert out == expected

これで、関数無いの値への依存はなくせた。
そのおかげで1つの関数で複数のテスト値が試せるように。

ただ、まだハードコーディングしているため、このままだと書き写すのに時間がかかってしまう。
テストファイルにコピペして、それを読み込むようにしたいなぁ...
ってことで、どんな感じでデータを扱いたいか決める。
>testcase.txt
5

3

1

2

8

2

4

0

こんな感じなら、すぐにコピペで済みそう。
さてさて、扱うデータの形を決めたら読み込み、変換の関数を...書きました。
(全部書くと長くなるので割愛)
getTestCase()

test_paiza.pyの中身は完成。

>test_paiza.py
import main
import pytest

def getTestCase():
   ..........#ここに読み込む関数を書く

detabase = getTestCase()
inputMessage = "testCase,expected"

@pytest.mark.parametrize(inputMessage,detabase)
def test(testCase,expected):
    test = main.program(input)
    test.start()
    out,err = capsys.readouterr()
    assert out == expected

さてさて、次に考えないといけないのは...
テストができたし、main.pyにどんな感じに課題コードを書くか決めないとなぁ...

さっきの割り算の問題をpaiza環境で書くとこんな感じ

num1 = input()
num2 = input()
print(num1/num2)
print(num1%num2)

ただ、pythonの標準入力関数input()を使っているが、実際にテストするときに手動入力は勘弁願いたい。
というわけで、完全にコピペで済むようにすることはあきらめて、こんな感じにする。

class program:
    def __init__(self.input:list):
        self.testcase =input

    def input(self):
        out = self.testcase[0]
        self.testcase.pop(0)
        return out

    def start(self):
        num1 = self.input()
        num2 = self.input()
        print(num1/num2)
        print(num1%num2)

これなら、start()の部分をコピペして、selfを消せば大丈夫ですね。
とはいえ、少しだけ見た目が悪い...
コンストラクタとinput()は親クラスに持たせてファイルを分割し、継承する形でprogramクラスを実装しましょう。
>main.py
from testTool import Drive

class program(Drive):
    def start(self):
        ・・・・・

あとは、testTool.pyにDriveクラスを移せば本日の作業終了です。

>testTool.py
class Drive:
    def __init__(self.input:list):
        self.testcase =input

    def input(self):
        out = self.testcase[0]
        self.testcase.pop(0)
        return out

    def start(self):
        pass



感想
実際に使ってみた感じ、とてもいい感じでした。
Cクラス問題までは、ブラウザで書きなぐったほうが早いですが、Bクラス問題くらいになると、自分の慣れた環境のほうがいいかなぁと。
今回プログラミングのスキルチェックを行う上で、アルゴリズムを考える能力だけが、プログラマーの実力じゃないなと思いました。
paizaスキルチェックでは、速さと正確さが求められている品質です。
これを達成するために、何をしてもいいと考えたとき(カンニングはだめですよ)、自分がどのようなスキルを持っていて、何ができるか、どうやって解決するかを見極めることも実力なのかなぁと思いました。

2018年10月20日土曜日

テスト駆動開発の練習をする環境を作りたい

時間があるときに、少しずつ進めるためのTODOリスト
<Git>
MVCodeからgithubにコミットできるようにしたい

<jenkins>
git hubが更新されたらテストを開始したい
pytestを使ったテストをできるようにしたい

<Pytest>
ユニットテストを行えるようにしたい
静的解析で、コード規約を確認したい
HTML出力を行いたい


今のところやってみたいのはこんな感じ
CIツールとかいうのを使ってみたい
テスト駆動開発のテスト速度についていけるのかね
まあ作ってみてから考えましょ

2018年10月13日土曜日

Dockerでpython環境を構築したい

Udemyのcomplete-python-bootcamp買っちゃった!(衝動買い)
こんな感じの
ついでに、講師のgitHubから飛んで買えば安くなるかも?よくわかんないけど

というわけで、環境構築
動画だと、Anaconda使うみたいっすね
ただ、動画通りにやっても面白くないし、自分のパソコンにはすでにAnaconda入ってるし
そして何より、環境分離したいし

てことで、今回はDockerつかってやろうかなーと

(現在2018/10/13)
(基本すべての作業をPowerShellで行っています)

今回の最終目標
1.Python3.7が使えるlinux環境を作る
2.Anacondaを使えるようにする
3.Jupyter notebookを使えるようにする
4.docker内でやる