summaryrefslogtreecommitdiff
path: root/src/miinaharava/tests
diff options
context:
space:
mode:
Diffstat (limited to 'src/miinaharava/tests')
-rw-r--r--src/miinaharava/tests/__init__.py0
-rw-r--r--src/miinaharava/tests/test_app.py241
-rw-r--r--src/miinaharava/tests/test_board.py295
-rw-r--r--src/miinaharava/tests/test_bot.py54
4 files changed, 590 insertions, 0 deletions
diff --git a/src/miinaharava/tests/__init__.py b/src/miinaharava/tests/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/miinaharava/tests/__init__.py
diff --git a/src/miinaharava/tests/test_app.py b/src/miinaharava/tests/test_app.py
new file mode 100644
index 0000000..1d13a71
--- /dev/null
+++ b/src/miinaharava/tests/test_app.py
@@ -0,0 +1,241 @@
+"""test_app.py - Testaa pelin suoritusta"""
+# pylint: disable = missing-class-docstring, too-few-public-methods
+
+from io import StringIO
+import unittest
+from unittest.mock import patch
+
+from app import App
+
+from tui import Action
+
+
+class KbdTest:
+ # pylint: disable = unused-argument, missing-function-docstring
+ def __init__(self, actions):
+ self.actions = actions
+ def read_action(self):
+ if self.actions:
+ action, _, _ = self.actions.pop(0)
+ else:
+ action = Action.NOOP
+ return action
+ def read_matrix_action(self, w, h, x, y):
+ return self.actions.pop(0) if self.actions else (Action.NOOP,x,y)
+
+
+class TestAppClass(unittest.TestCase):
+ """ Testit itse appille """
+ class DefaultArgs:
+ autoplay = 2
+ intermediate = None
+ expert = None
+ board = None
+ mines = None
+ size = None
+ bot = None
+ quiet = None
+ delay = None
+
+ sure_win_board = [
+ [0,0,0,0,0,0,0,0,0],
+ [0,0,0,0,0,0,0,0,0],
+ [0,0,0,0,0,0,0,0,0],
+ [0,0,0,0,0,0,0,0,0],
+ [0,0,0,0,1,0,0,0,0],
+ [0,0,0,0,0,0,0,0,0],
+ [0,0,0,0,0,0,0,0,0],
+ [0,0,0,0,0,0,0,0,0],
+ [0,0,0,0,0,0,0,0,0]
+ ]
+
+ sure_lose_board = [
+ [1,1,1,1,1,1,1,1,1],
+ [1,1,1,1,1,1,1,1,1],
+ [1,1,1,1,1,1,1,1,1],
+ [1,1,1,1,1,1,1,1,1],
+ [1,1,1,1,0,1,1,1,1],
+ [1,1,1,1,1,1,1,1,1],
+ [1,1,1,1,1,1,1,1,1],
+ [1,1,1,1,1,1,1,1,1],
+ [1,1,1,1,1,1,1,1,1]
+ ]
+
+ dssp_win_board = [
+ [0,0,0,0,0,0,0,0,0],
+ [0,0,0,0,0,0,0,0,0],
+ [0,0,0,0,0,0,0,0,0],
+ [0,0,0,0,0,0,0,0,0],
+ [0,0,0,0,0,0,0,0,0],
+ [0,0,0,0,0,0,0,0,0],
+ [0,0,0,0,0,0,0,0,0],
+ [0,0,0,0,0,0,0,0,0],
+ [0,1,1,0,1,1,0,1,0]
+ ]
+
+ mini_board = [
+ [0,0],
+ [0,1]
+ ]
+
+
+ def test_run(self):
+ """ Testataan että edes pyörähtää """
+ app = App(self.DefaultArgs)
+ app.run()
+ del app
+
+ def test_quit(self):
+ """ Testataan Quittaamista """
+ app = App()
+ app.ui.kbd=KbdTest([
+ (Action.QUIT,0,0),
+ (Action.OPEN,0,0)
+ ])
+ app.run()
+ del app
+
+ def test_many_games(self):
+ """ Varman voiton lauta palauttaa true """
+ class Args(self.DefaultArgs):
+ quiet = True
+ for _ in range(50):
+ app = App(Args)
+ app.run()
+ del app
+ Args.intermediate = True
+ for _ in range(20):
+ app = App(Args)
+ app.run()
+ del app
+ Args.expert = True
+ for _ in range(10):
+ app = App(Args)
+ app.run()
+ del app
+
+ def test_sure_win(self):
+ """ Varman voiton lauta palauttaa true """
+ class Args(self.DefaultArgs):
+ board = self.sure_win_board
+ quiet = True
+ app = App(Args)
+ self.assertTrue(app.run())
+ del app
+
+ def test_dssp_win(self):
+ """ Varman voiton lauta palauttaa true """
+ class Args(self.DefaultArgs):
+ board = self.dssp_win_board
+ app = App(Args)
+ self.assertTrue(app.run())
+ del app
+
+ def test_no_dssp_win_with_simple(self):
+ """ Varman voiton lauta palauttaa true """
+ class Args(self.DefaultArgs):
+ board = self.dssp_win_board
+ quiet = True
+ bot = 1
+ while True:
+ app = App(Args)
+ if not app.run():
+ break
+ del app
+
+ def test_sure_lose(self):
+ """ Varman häviön lauta palauttaa false """
+ class Args(self.DefaultArgs):
+ board = self.sure_lose_board
+ app = App(Args)
+ self.assertFalse(app.run())
+ del app
+
+ def test_custom_size(self):
+ """ Varman häviön lauta palauttaa false """
+ class Args(self.DefaultArgs):
+ size = (4, 4)
+ with patch('sys.stdout', new = StringIO()) as captured:
+ app = App(Args)
+ app.run()
+ self.assertIn("Mukautettu (4x4", captured.getvalue())
+ del app
+
+ def test_sure_win_with_actions(self):
+ """ Varman voiton lauta palauttaa true """
+ class Args(self.DefaultArgs):
+ board = self.sure_win_board
+ autoplay = 0
+ bot = 0
+ app = App(Args)
+ app.ui.kbd=KbdTest([
+ (Action.SAFE,0,0),
+ (Action.OPEN,0,0)
+ ])
+ self.assertTrue(app.run())
+ del app
+
+ def test_sure_lose_with_actions(self):
+ """ Varman voiton lauta palauttaa true """
+ class Args(self.DefaultArgs):
+ board = self.sure_lose_board
+ autoplay = 0
+ app = App(Args)
+ app.ui.kbd=KbdTest([
+ (Action.FLAG,0,0),
+ (Action.MINE,0,0),
+ (Action.OPEN,0,0)
+ ])
+ self.assertFalse(app.run())
+ del app
+
+ def test_auto_play_hints(self):
+ """ Vihjeiden automaattipelaaminen toimii """
+ class Args(self.DefaultArgs):
+ board = self.dssp_win_board
+ autoplay = 1
+ app = App(Args)
+ app.ui.kbd=KbdTest([
+ (Action.OPEN,0,0),
+ (Action.HINT,0,0),
+ ])
+ self.assertTrue(app.run())
+ del app
+
+ def test_delay(self):
+ """ Hidastus toimii """
+ class Args(self.DefaultArgs):
+ board = self.dssp_win_board
+ delay = 5
+ app = App(Args)
+ with patch('time.sleep') as patched_sleep:
+ self.assertTrue(app.run())
+ del app
+ patched_sleep.assert_called()
+
+ def test_delay_can_be_off(self):
+ """ Hidastus ei ole aina päälle """
+ class Args(self.DefaultArgs):
+ board = self.dssp_win_board
+ app = App(Args)
+ with patch('time.sleep') as patched_sleep:
+ self.assertTrue(app.run())
+ del app
+ patched_sleep.assert_not_called()
+
+ def test_botless_play(self):
+ """ Hidastus toimii """
+ class Args(self.DefaultArgs):
+ board = self.mini_board
+ autoplay = 0
+ delay = 50000
+ app = App(Args)
+ app.ui.kbd=KbdTest([
+ (Action.OPEN,0,0),
+ (Action.HINT,0,0),
+ (Action.OPEN,1,0),
+ (Action.HINT,0,0),
+ (Action.OPEN,0,1)
+ ])
+ self.assertTrue(app.run())
+ del app
diff --git a/src/miinaharava/tests/test_board.py b/src/miinaharava/tests/test_board.py
new file mode 100644
index 0000000..8aeac89
--- /dev/null
+++ b/src/miinaharava/tests/test_board.py
@@ -0,0 +1,295 @@
+""" tests/test_board.py - Testit pelilaudalle """
+
+import unittest
+
+from board import Board, Level, LevelSpecs
+
+def matrix_equals(m1, m2):
+ """ matrix_equals - apufunktio testaa onko matriisit samat """
+ if len(m1)!=len(m2):
+ return False
+ # pylint: disable = consider-using-enumerate
+ for i in range(len(m1)):
+ if m1[i] != m2[i]:
+ return False
+ return True
+
+def matrix_swap_xy(m):
+ """ matrix_swap_xy - palauttaa matriisin korvattu x -> y ja y -> x """
+ if not m:
+ return None
+ w, h = len(m[0]), len(m)
+ ret_m = [[0 for _ in range(h)] for _ in range(w)]
+ for y in range(h):
+ for x in range(w):
+ ret_m[x][y]=m[y][x]
+ return ret_m
+
+
+class TestBoardClass(unittest.TestCase):
+ """ pelilauden testit kattava luokka """
+
+ def test_init_works_and_defaults_beginner(self):
+ """ pelilautaolion luominen onnistuu ja defaulttaa aloittelijaksi """
+ b = Board()
+ self.assertEqual(b.get_width(), LevelSpecs[Level.BEGINNER][0])
+ self.assertEqual(b.get_height(), LevelSpecs[Level.BEGINNER][1])
+ self.assertEqual(b.get_mines(), LevelSpecs[Level.BEGINNER][2])
+ self.assertTrue(b.get_width()>0)
+
+
+ def test_init_with_level(self):
+ """ olion luominen onnistuu vaikeustasolla"""
+ b = Board(level=Level.EXPERT)
+ self.assertEqual(b.get_width(), LevelSpecs[Level.EXPERT][0])
+ self.assertEqual(b.get_height(), LevelSpecs[Level.EXPERT][1])
+ self.assertEqual(b.get_mines(), LevelSpecs[Level.EXPERT][2])
+
+
+ def test_init_with_custom_dimentions(self):
+ """ mukautetun kentän luominen onnistuu """
+ b = Board(width=13, height=14, mines=15)
+ self.assertEqual(b.get_width(), 13)
+ self.assertEqual(b.get_height(), 14)
+ self.assertEqual(b.get_mines(), 15)
+ b = Board(width=22, height=12)
+ self.assertEqual(b.get_width(), 22)
+ self.assertEqual(b.get_height(), 12)
+ self.assertEqual(b.get_mines(), 22)
+
+
+ def test_init_with_incorect_dimensions(self):
+ """ luominen ei saa onnitua mahdottomilla mitoilla """
+ b = Board(width=1, height=999, mines=0)
+ self.assertEqual(b.get_width(), LevelSpecs[Level.BEGINNER][0])
+ self.assertEqual(b.get_height(), LevelSpecs[Level.BEGINNER][1])
+ self.assertEqual(b.get_mines(), LevelSpecs[Level.BEGINNER][2])
+
+
+ def test_init_with_valid_board(self):
+ """ Pelilaudan luominen onnistuu kelvollisella asettelulla """
+ t = [
+ [0,0,0,0],
+ [0,0,0,1],
+ [0,0,0,0]
+ ]
+ b = Board(board = t)
+ self.assertEqual(b.get_width(), 4)
+ self.assertEqual(b.get_height(), 3)
+ self.assertEqual(b.get_mines(), 1)
+
+
+ def test_init_with_invalid_board(self):
+ """ Yritetään luoda peli kelvottomalla laudalla """
+ t = [
+ [0,0,0,0,0],
+ [0,0,0,1],
+ [0,0,0,0,0]
+ ]
+ b = Board(board = t)
+ # Resetoituihan aloittelijan lauta
+ self.assertIn(LevelSpecs[Level.BEGINNER][3], b.get_level_name())
+
+ t = [
+ [0,1,0,0,0],
+ ]
+ b = Board(board = t)
+ self.assertIn(LevelSpecs[Level.BEGINNER][3], b.get_level_name())
+
+ t = [
+ [0,0,0,0],
+ [0,0,0,0],
+ [0,0,0,0]
+ ]
+ b = Board(board = t)
+ self.assertIn(LevelSpecs[Level.BEGINNER][3], b.get_level_name())
+
+ t = [
+ [1,1,1],
+ [1,1,1],
+ [1,1,1]
+ ]
+ b = Board(board = t)
+ self.assertIn(LevelSpecs[Level.BEGINNER][3], b.get_level_name())
+
+
+ def test_tiles_and_masks_ok(self):
+ """ Luohan luokka sisäiset laatat ja maskit oikein """
+ # pylint: disable = protected-access
+ t = [
+ [0,0,0,0],
+ [0,0,0,1],
+ [0,0,0,0]
+ ]
+ b = Board(board = t)
+ self.assertEqual(b.get_width(), 4)
+ self.assertEqual(b.get_height(), 3)
+ self.assertEqual(b.get_mines(), 1)
+
+ # testataan onko laatat tallennettu oikein luokkaan
+ t = matrix_swap_xy([
+ [0,0,1,1],
+ [0,0,1,9],
+ [0,0,1,1]
+ ])
+ self.assertTrue(matrix_equals(b._Board__tiles, t))
+
+ # onko maksit asetettu oikein
+ t = matrix_swap_xy([
+ [12,12,12,12],
+ [12,12,12,12],
+ [12,12,12,12]
+ ])
+ self.assertTrue(matrix_equals(b._Board__masked, t))
+
+
+ def test_get_view_and_guess(self):
+ """ laudan näkymä on oikein senkin jälkeen kun on arvattu """
+
+ t = [
+ [0,0,1],
+ [0,0,0],
+ [0,0,0]
+ ]
+ b = Board(board=t)
+
+ # Antaahan pelikenttä pelkkää maskia aluksi
+ t = matrix_swap_xy([
+ [12,12,12],
+ [12,12,12],
+ [12,12,12]
+ ])
+ self.assertTrue(matrix_equals(b.get_view(), t))
+
+ # avataan yläkulma -> palatuu True
+ self.assertTrue(b.guess(0,0))
+
+ # onko näkymä nyt oikein
+ t = matrix_swap_xy([
+ [0,1,12],
+ [0,1,1],
+ [0,0,0]
+ ])
+ self.assertTrue(matrix_equals(b.get_view(), t))
+
+ # avataan alakulma jossa miina -> palautuu False
+ self.assertFalse(b.guess(2,0))
+
+
+ def test_is_winning(self):
+ """ toimiiko voittotilanteen tunnistus """
+
+ t = [
+ [0,1],
+ [0,0],
+ ]
+ b = Board(board=t)
+ self.assertFalse(b.is_winning())
+
+ # Avataan ruutu jolla ei tule viellä voittoa
+ t = matrix_swap_xy([
+ [1,12],
+ [12,12]
+ ])
+ self.assertTrue(b.guess(0,0))
+ self.assertTrue(matrix_equals(b.get_view(), t))
+ self.assertFalse(b.is_winning())
+
+ # Avataan loputkin ruudut, jolloin pitäisi voittaa
+ t = matrix_swap_xy([
+ [1,12],
+ [1,1]
+ ])
+ self.assertTrue(b.guess(0,1))
+ self.assertTrue(b.guess(1,1))
+ self.assertTrue(matrix_equals(b.get_view(), t))
+ self.assertTrue(b.is_winning())
+
+ # Lupuksi avataan miina jolloin voittoa ei enää pitäisi olla
+ t = matrix_swap_xy([
+ [1,9],
+ [1,1]
+ ])
+ self.assertFalse(b.guess(1,0))
+ self.assertTrue(matrix_equals(b.get_view(), t))
+ self.assertFalse(b.is_winning())
+
+
+ def test_error_conditions_in_guess(self):
+ """ ruudun avaus alueen ulkopuolelta tai avatussa ruudussa ei onnistu"""
+ t = [
+ [0,1],
+ [0,0],
+ ]
+ b = Board(board=t)
+ self.assertFalse(b.guess(2,2))
+ self.assertTrue(b.guess(0,0))
+ self.assertFalse(b.guess(0,0))
+
+
+ def test_get_mask(self):
+ """ maski annetaan oikein """
+ t = [
+ [1,0],
+ [0,0],
+ ]
+ b = Board(board=t)
+ self.assertEqual(b.get_mask(1,0), 12)
+ self.assertTrue(b.guess(1,0))
+ self.assertFalse(b.get_mask(1,0))
+
+
+ def test_flag(self):
+ """ ruudun lipun vaihto ja asetus toimii """
+ t = [
+ [0,0],
+ [0,1],
+ ]
+ b = Board(board=t)
+ self.assertEqual(b.get_mask(0,0), 12)
+ self.assertTrue(b.flag(0,0))
+ self.assertEqual(b.get_mask(0,0), 13)
+ self.assertTrue(b.flag(0,0))
+ self.assertEqual(b.get_mask(0,0), 10)
+ self.assertTrue(b.flag(0,0))
+ self.assertEqual(b.get_mask(0,0), 11)
+ self.assertTrue(b.flag(0,0))
+ self.assertEqual(b.get_mask(0,0), 12)
+ self.assertTrue(b.flag(0,0,10))
+ self.assertEqual(b.get_mask(0,0), 10)
+
+
+ def test_flag_error_conditions(self):
+ """ liputus ei onnistu jos avattu, alueen ulkopuolella, outo arvo """
+ t = [
+ [0,1],
+ [1,1],
+ ]
+ b = Board(board=t)
+ self.assertFalse(b.flag(0,0,6)) # Lippu jota ei ole
+ self.assertFalse(b.flag(2,2)) # Alueen ulkopuolella
+ self.assertTrue(b.guess(0,0))
+ self.assertFalse(b.flag(0,0)) # Avattu laatta
+
+
+ def test_reveal(self):
+ """ paljastuksen jälkeen näkyy laatat sellaisenaan """
+ t = [
+ [0,1],
+ [1,1],
+ ]
+ b = Board(board=t)
+ b.reveal()
+ t = matrix_swap_xy([
+ [3,9],
+ [9,9]
+ ])
+ self.assertTrue(matrix_equals(b.get_view(), t))
+
+
+ def test_get_level_name(self):
+ """ Testataan että nykyinen vaikeustaso palautuu oikein """
+ b = Board(level=Level.INTERMEDIATE)
+ self.assertIn(LevelSpecs[Level.INTERMEDIATE][3], b.get_level_name())
+ b = Board(level=Level.INTERMEDIATE, width=25, mines=2)
+ self.assertIn("Mukautettu", b.get_level_name())
diff --git a/src/miinaharava/tests/test_bot.py b/src/miinaharava/tests/test_bot.py
new file mode 100644
index 0000000..4dab148
--- /dev/null
+++ b/src/miinaharava/tests/test_bot.py
@@ -0,0 +1,54 @@
+""" tests/test_bot.py - Testaa botin toimintaa"""
+# pylint: disable = missing-class-docstring, too-few-public-methods, protected-access
+
+import unittest
+
+from board import Board, Tile
+from bots import DSSPBot, SimpleBot
+from tui import Action
+
+class TestBotClass(unittest.TestCase):
+ """ botin testit"""
+ def test_init(self):
+ """ olioden luominen onnistuu """
+ DSSPBot()
+ SimpleBot()
+
+ def correctly_marking(self, open_free=False, bot_type=DSSPBot):
+ """ Testaa onko miinat miinoja ja vapaat vapaita alkuun avatusta """
+ for _ in range(500):
+ brd = Board()
+ # jos ei aukea ylälaidasta otetaan seuraava
+ if not brd.guess(0,0):
+ continue
+ # vain varmat liikut
+ bot = bot_type(uncertain=False)
+
+ tested = set()
+ while True:
+ action, x, y = bot.hint(brd.get_view(), 0, 0)
+ if (x,y) in tested:
+ break
+ tested.add((x,y))
+ if action == Action.SAFE:
+ self.assertTrue( brd._Board__tiles[x][y] < Tile.MINE )
+ if open_free:
+ brd.guess(x,y)
+ if action == Action.MINE:
+ self.assertTrue( brd._Board__tiles[x][y] == Tile.MINE )
+
+ def test_dssp_marks_correctly_with_open(self):
+ """ Testaa onko dssp:n miinat miinoja ja avaa vapaat """
+ self.correctly_marking(True, DSSPBot)
+
+ def test_simple_marks_correctly_with_open(self):
+ """ Testaa onko dssp:n miinat miinoja ja avaa vapaat """
+ self.correctly_marking(True, SimpleBot)
+
+ def test_dssp_marks_correctly(self):
+ """ Testaa onko dssp:n miinat miinoja ja vapaat vapaita """
+ self.correctly_marking(False, DSSPBot)
+
+ def test_simple_marks_correctly(self):
+ """ Testaa onko simple:n miinat miinoja ja vapaat vapaita """
+ self.correctly_marking(False, SimpleBot)