テストでバグ発見!(2)自動販売機シミュレーターのバグを見つけろ!:山浦恒央の“くみこみ”な話(144)(4/4 ページ)
提示された仕様とプログラム(バグを含む)から、自身の手でテストケースを設計し、バグを実際に見つけ、バグレポートまでを作成する実践的なシリーズ「テストでバグ発見!」。第2回は、自動販売機シミュレーターのプログラムからバグを見つけ出しましょう。
付録
VendingMachine.pyをダウンロードする際にファイルが開けない、またはセキュリティの観点からWebサイトからファイルをダウンロードして開きたくない場合、下記のソースコードのテキストをコピーして使用してください。なお、プログラミング言語は、Python 3.9.5で動作します(Windows 10環境上で、動作確認済み)。
# # プログラム:自動販売機シミュレータ(VendingMachine.py) # 作成者:T.Yamaura, Y.Ohmori # import tkinter as tk class VendingMachine(tk.Frame): def __init__(self,master): super().__init__(master) self.pack() #ウィンドウサイズ設定 master.geometry('480x270') master.maxsize(width=480, height=270) master.minsize(width=480, height=270) master.resizable(0,0) master.title("自動販売機シミュレータ") canvas = tk.Canvas(master, height=300,width=500) canvas.pack() #商品データ定義 self.depositMoney = tk.IntVar() self.depositMoney.set(0) self.price = [100, 140, 120, 80, 100, 140, 120, 300] self.name = ['コーラ', 'オレンジ', 'サイダー', 'スポドリ', 'コーヒー', 'お茶', '紅茶', 'ビール'] self.dpt = [5000, 1000, 500, 100, 50, 10] self.stock = [5, 4, 12, 8, 2, 9, 5, 3] #商品エリア canvas.create_rectangle(10, 15, 230, 200) ItemAreaLabel = tk.Label(text='商品エリア') ItemAreaLabel.place(x = 15, y = 25) #商品エリアのボタン button1 = tk.Button(master, text = self.name[0] + '\n(' + str(self.price[0]) + '円)', command=self.BtnAction(0), width=5, height=3).place(x=20,y=50) button2 = tk.Button(master, text = self.name[1] + '\n(' + str(self.price[1]) + '円)', command=self.BtnAction(1), width=5, height=3).place(x=70,y=50) button3 = tk.Button(master, text = self.name[2] + '\n(' + str(self.price[2]) + '円)', command=self.BtnAction(2), width=5, height=3).place(x=120,y=50) button4 = tk.Button(master, text = self.name[3] + '\n(' + str(self.price[3]) + '円)', command=self.BtnAction(3), width=5, height=3).place(x=170,y=50) button5 = tk.Button(master, text = self.name[4] + '\n(' + str(self.price[4]) + '円)', command=self.BtnAction(4), width=5, height=3).place(x=20,y=120) button6 = tk.Button(master, text = self.name[5] + '\n(' + str(self.price[5]) + '円)', command=self.BtnAction(5), width=5, height=3).place(x=70,y=120) button7 = tk.Button(master, text = self.name[6] + '\n(' + str(self.price[6]) + '円)', command=self.BtnAction(6), width=5, height=3).place(x=120,y=120) button8 = tk.Button(master, text = self.name[7] + '\n(' + str(self.price[7]) + '円)', command=self.BtnAction(7), width=5, height=3).place(x=170,y=120) #総額エリア canvas.create_rectangle(230, 15, 470, 65) TotalAreaLabel = tk.Label(text='総額エリア') TotalAreaLabel.place(x = 240, y = 30) self.TotalLabel = tk.Label(text='0円') self.TotalLabel.place(x = 360, y = 30) TotalTitleLabel = tk.Label(text='総額') TotalTitleLabel.place(x = 330, y = 30) button = tk.Button(master, text = 'お釣り',command=self.exchange(), width=5, height=2).place(x=420,y=20) #金額投入エリア canvas.create_rectangle(230, 65, 470, 200) DepositLabel = tk.Label(text='金額投入エリア') DepositLabel.place(x = 240, y = 70) button = tk.Button(master, text = '5000円投入', command=self.dpsAction(0), width=8, height=2).place(x=240,y=90) button = tk.Button(master, text = '1000円投入', command=self.dpsAction(1),width=8, height=2).place(x=320,y=90) button = tk.Button(master, text = '500円投入', command=self.dpsAction(2),width=8, height=2).place(x=400,y=90) button = tk.Button(master, text = '100円投入', command=self.dpsAction(3),width=8, height=2).place(x=240,y=140) button = tk.Button(master, text = '50円投入', command=self.dpsAction(4),width=8, height=2).place(x=320,y=140) button = tk.Button(master, text = '10円投入', command=self.dpsAction(5),width=8, height=2).place(x=400,y=140) #メッセージエリア canvas.create_rectangle(10, 200, 470, 250) MsgAreaLabel = tk.Label(text='メッセージエリア:') MsgAreaLabel.place(x = 30, y = 215) self.MsgLabel = tk.Label(text='') self.MsgLabel.place(x = 110, y = 215) #商品購入時の処理 def BtnAction(self, index): def inner(): if self.depositMoney.get() >= self.price[index] and self.stock[index]-1 > 0: self.depositMoney.set(self.depositMoney.get() - self.price[index]) self.TotalLabel['text'] = str(self.depositMoney.get()) + '円' self.stock[index] = self.stock[index] - 1 self.MsgLabel['text'] = str(self.name[index]) + 'を購入しました' else: self.MsgLabel['text'] = '金額か在庫が足りません' return inner #お金投入時の処理 def dpsAction(self, index): def inner(): if self.depositMoney.get() < 10000: self.depositMoney.set(self.depositMoney.get() + self.dpt[index]) self.TotalLabel['text'] = str(self.depositMoney.get()) + '円' self.MsgLabel['text'] = str(self.dpt[index]) + '円を投入しました' else: self.MsgLabel['text'] = '上限金額より大きい金額を投入できません' return inner #お釣りボタン選択時の処理 def exchange(self): def inner(): self.MsgLabel['text'] = str(self.depositMoney.get()) + '円を排出しました' self.depositMoney.set(0) self.TotalLabel['text'] = str(self.depositMoney.get()) + '円' return inner def main(): formBase = tk.Tk() app = VendingMachine(master=formBase) app.mainloop() if __name__ == "__main__": main()
山浦先生の書籍が発売中です!
前シリーズ「ソフトウェア技術者のためのバグ百科事典」を大幅に加筆、修正した山浦恒央先生の書籍「ソフトウェア技術者のためのバグ検出テキスト」が日科技連出版から好評発売中です。連載でも取り上げた、「要求仕様書のバグ」「実装抜けのバグ」「テスト業務のバグ」など、バグを36種類に分類して解説しています。囲碁や将棋であれば、「相掛かり」「矢倉」「四間飛車」「藤井システム」のような戦法を網羅した内容になっています。
前著「ソフトウェア技術者のためのバグ検出ドリル」(2019年11月刊行)も好評発売中です。実際にバグを含む要求仕様書、設計書、コーディング、デバッグ、保守を具体的に取り上げ、練習問題として31問を出題しました。同書は、囲碁や将棋における「次の一手」的な問題であり、ピンポイントの場面を取り上げ、実践力を鍛えることを目的としています。
両書とも興味のある方は、Amazon.comや書店でチェックしてください!
東海大学 大学院 組込み技術研究科 非常勤講師(工学博士)
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
- ≫連載「山浦恒央の“くみこみ”な話」バックナンバー
- テストでバグ発見!(1)まずは成人判定プログラムでチュートリアル
今回から、提示された仕様とプログラム(バグを含む)から、自身の手でテストケースを設計し、バグを実際に見つけ、バグレポートまでを作成する実践的なシリーズ「テストでバグ発見!」が始まります。第1回は、チュートリアルとして成人判定プログラムからバグを発見してみましょう。 - ソフトウェア技術者のためのバグ百科事典(21)【総まとめ】バグの特定手順を解説
ソフトウェア技術者に向けて、バグに関する基礎知識をまとめていく新シリーズ「バグ百科事典」。第21回は、シリーズの総まとめとして、バグの検出から修正までの「バグ特定手順」の一連の流れを解説します。 - ソフトウェア技術者のためのバグ百科事典(20)みずほ銀行は人ごとではない!? システム刷新のバグ
ソフトウェア技術者に向けて、バグに関する基礎知識をまとめていく新シリーズ「バグ百科事典」。第20回は、「IT業界のサグラダファミリア」と呼ばれたみずほ銀行の事例に代表されるシステム刷新のバグを紹介します。 - ソフトウェア技術者のためのバグ百科事典(19)複雑怪奇な通信系プログラムのバグ
ソフトウェア技術者に向けて、バグに関する基礎知識をまとめていく新シリーズ「バグ百科事典」。第19回は、複雑怪奇になりがちな通信系プログラムのバグを紹介します。 - ソフトウェア技術者のためのバグ百科事典(18)開発工数の半分を占めるテストのバグのケーススタディー
ソフトウェア技術者に向けて、バグに関する基礎知識をまとめていく新シリーズ「バグ百科事典」。第18回は、開発工数の半分を占めるテストのバグのケーススタディーを紹介します。 - ソフトウェア技術者のためのバグ百科事典(17)無限ループやbreak抜け、コーディングのバグ再び
ソフトウェア技術者に向けて、バグに関する基礎知識をまとめていく新シリーズ「バグ百科事典」。第17回は、第14回でテーマにしたコーディングのバグを再び取り上げます。無限ループやbreak抜けなどまだまだあります!