From ba6d9d5792745223afe2852fb8632680a28aa7a8 Mon Sep 17 00:00:00 2001 From: Kazuki Ueki Date: Thu, 18 Nov 2021 10:38:43 +0900 Subject: [PATCH] =?UTF-8?q?=E3=82=B3=E3=83=9E=E3=83=B3=E3=83=89=E3=83=A9?= =?UTF-8?q?=E3=82=A4=E3=83=B3=E3=81=8B=E3=82=89=E3=83=91=E3=83=A9=E3=83=A1?= =?UTF-8?q?=E3=83=BC=E3=82=BF=E3=83=BC=E3=82=92=E6=B8=A1=E3=81=9B=E3=82=8B?= =?UTF-8?q?=E6=A9=9F=E8=83=BD=E3=82=92=E8=BF=BD=E5=8A=A0=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit f18a910fc6f9a8701335609be9b92754715c50cf Author: Kazuki Ueki Date: Thu Nov 18 10:34:26 2021 +0900 flake8の警告にあわせて修正する commit 14dfcae1d6dd3ec8f90371115edefbb2eea8ad4b Author: Kazuki Ueki Date: Thu Nov 18 10:32:46 2021 +0900 ユニットテストを追加する commit 67036bd6505b2aff4dbdb709de2834b877d6a9c0 Author: Kazuki Ueki Date: Thu Nov 18 10:30:30 2021 +0900 ポート番号等にデフォルト値を設定する commit 438e239cc27326789cdb0e169e001144b404d484 Author: Kazuki Ueki Date: Thu Nov 18 10:28:42 2021 +0900 コマンドラインからパラメーターを渡せる機能を追加する --- CHaser.py | 50 +++++++++++++++++---- test_CHaser.py | 118 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+), 9 deletions(-) create mode 100644 test_CHaser.py diff --git a/CHaser.py b/CHaser.py index b8ef6a5..63964c9 100644 --- a/CHaser.py +++ b/CHaser.py @@ -1,12 +1,38 @@ import socket import ipaddress import os +import getopt +import sys + class Client: def __init__(self): - self.port = input("ポート番号を入力してください → ") - self.name = input("ユーザー名を入力してください → ")[:15] - self.host = input("サーバーのIPアドレスを入力してください → ") + if len(sys.argv) > 1: + try: + optlist, args = getopt.getopt(sys.argv[1:], 'h:n:p:') + except getopt.GetoptError as err: + print(err) # will print something like "option -a not recognized" + sys.exit(2) + for o, a in optlist: + if o == '-n': + self.name = a + elif o == '-p': + self.port = a + elif o == '-h': + self.host = a + else: + assert False, "unhandled option" + else: + self.port = input("ポート番号を入力してください → ") + self.name = input("ユーザー名を入力してください → ")[:15] + self.host = input("サーバーのIPアドレスを入力してください → ") + + if not self.port: + self.port = 2009 + if not self.name: + self.name = 'User1' + if not self.host: + self.host = '127.0.0.1' if not self.__ip_judge(self.host): os._exit(1) @@ -32,32 +58,39 @@ def __ip_judge(self, host): def __str_send(self, send_str): try: self.client.sendall(send_str.encode("utf-8")) - except: + except Exception: print("send error:{0}\0".format(send_str)) - def __order(self, order_str, gr_flag = False): + def __order(self, order_str, gr_flag=False): + """ + @order_str (strig): Command. must be 2 chars and upper case. + @gr_flag (boolean): GetReady flag. + """ try: if gr_flag: responce = self.client.recv(4096) if(b'@' in responce): - pass # Connection completed. + pass # Connection completed. else: - print("Connection failed.") + print("Connection failed. {0}".format(responce)) self.__str_send(order_str + "\r\n") + # response is 11 digits integer. responce = self.client.recv(4096)[0:11].decode("utf-8") if not gr_flag: self.__str_send("#\r\n") + # if first digit is `0` game is over. if responce[0] == '1': return [int(x) for x in responce[1:10]] elif responce[0] == '0': raise OSError("Game Set!") else: - print("responce[0] = {0} : Response error.".format(responce[0])) + msg = "responce[0] = {0} : Response error." + print(msg.format(responce[0])) raise OSError("Responce Error") except OSError as e: @@ -115,4 +148,3 @@ def put_left(self): def put_down(self): return self.__order("pd") - \ No newline at end of file diff --git a/test_CHaser.py b/test_CHaser.py new file mode 100644 index 0000000..19a6b0c --- /dev/null +++ b/test_CHaser.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from io import StringIO +import contextlib +import sys +import unittest +import CHaser + + +class contextlib_redirect_stdin(contextlib._RedirectStream): + """ + 標準入力を横取りするためのおまじない + """ + _stream = "stdin" + + +class TestCHaser(unittest.TestCase): + """ + contextlibを使って標準入力・出力・エラーを横取りし + Clientの起動パラメーターを渡してのテストを行う + """ + def tearDown(self) -> None: + """ + sys.argvはテストケースをまたいで残るため都度リセットする + """ + del sys.argv[1:] + return super().tearDown() + + def test_noargs(self): + """ + コマンドライン引数なしでClientを初期化したテストケース + StringIOを使って input 関数に入力を行う + """ + buf_in = StringIO() + buf_in.write("9999\n") + buf_in.write("MyName\n") + buf_in.write("0.0.0.0\n") + buf_in.seek(0) + buf_out = StringIO() + buf_err = StringIO() + with contextlib.redirect_stdout(buf_out), \ + contextlib.redirect_stderr(buf_err), \ + contextlib_redirect_stdin(buf_in): + try: + client = CHaser.Client() + self.assertEquals(9999, client.port) + self.assertEquals("MyName", client.name) + self.assertEquals("0.0.0.0", client.host) + except ConnectionRefusedError: + pass + + def test_default_values(self): + """ + inputに空文字列を送った場合のテストケース + """ + buf_in = StringIO() + buf_in.write("\n") + buf_in.write("\n") + buf_in.write("\n") + buf_in.seek(0) + buf_out = StringIO() + buf_err = StringIO() + with contextlib.redirect_stdout(buf_out), \ + contextlib.redirect_stderr(buf_err), \ + contextlib_redirect_stdin(buf_in): + try: + client = CHaser.Client() + self.assertEquals(2009, client.port) + self.assertEquals("User1", client.name) + self.assertEquals("127.0.0.1", client.host) + except ConnectionRefusedError: + pass + + def test_argv(self): + """ + コマンドライン引数を渡してClientを初期化したテストケース + """ + sys.argv.append("-p") + sys.argv.append("2010") + sys.argv.append("-n") + sys.argv.append("User2") + sys.argv.append("-h") + sys.argv.append("127.0.0.1") + buf_in = StringIO() + buf_out = StringIO() + buf_err = StringIO() + with contextlib.redirect_stdout(buf_out), \ + contextlib.redirect_stderr(buf_err), \ + contextlib_redirect_stdin(buf_in): + try: + client = CHaser.Client() + self.assertEquals(2010, client.port) + self.assertEquals("User2", client.name) + self.assertEquals("127.0.0.1", client.host) + except ConnectionRefusedError: + pass + + def test_invalid_argv(self): + """ + 不正なコマンドライン引数を渡したテストケース + """ + sys.argv.append("-a") + buf_in = StringIO() + buf_out = StringIO() + buf_err = StringIO() + with contextlib.redirect_stdout(buf_out), \ + contextlib.redirect_stderr(buf_err), \ + contextlib_redirect_stdin(buf_in): + try: + CHaser.Client() + except SystemExit: + expect = "option -a not recognized\n" + self.assertEquals(expect, buf_out.getvalue()) + + +if __name__ == '__main__': + unittest.main()