Kihagyás

7. gyakorlat

Szerkesztés alatt!

Az oldal további része szerkesztés alatt áll, a tartalma minden további értesítés nélkül többször, gyakran, jelentősen megváltozhat!

Tesztelés

Lefedettség (coverage)

A kódlefedettség (code coverage) azt mutatja, hogy a tesztek (együtt) a kód mekkora részét fedték le/futtatták tesztelés közben. Törekedni kell a 100%-os kódlefedettségre, kisebb érték esetén ugyanis biztos, hogy lesznek olyan kódrészletek, amiket a tesztek nem ellenőriztek le.

Tesztesetek készítése

A conftest.py lehetőséget ad a tesztelés konfigurálására. A lehetőségek közül hármat emelnénk most ki:

  • sys.path beállítása: Alapesetben a pytest az indítási mappát veszi kezdőkönyvtárnak, ehhez viszonyítva keres modulokat és csomagokat. Ha viszont a mi könyvtárszerkezetünkben van mondjuk egy közbeiktatott src/ mappa is, akkor a tesztek import utasításai nem működnek. Ilyenkor a sys.path változó felülírásával/módosításával el lehet érni, hogy az pytest először az src/ mappában keressen modulokat és csomagokat.
  • pytest_run_setup(item) függvény: Ez a függvény minden egyes teszt előtt lefut. Arra (is) jó, hogy minden teszt előtt beállítsunk egy egységes hívási környezetet.
  • pytest_run_teardown(item) függvény: Ez a függvény minden egyes teszt után lefut. Ha a tesztek után mondjuk "takarítani" kell, azt ki lehet ide szervezni.
Feladat: készíts teszteket a dice program függvényeihez

Adott a következő dice program:

src/dice.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#!/usr/bin/env python3
"""
Szoftverfesztelési folyamatok példaprogram
SZTE TTIK, Informatikai Intézet, Szoftverfejlesztés Tanszék
cc-by-nc-nd
"""

import random

"""
A függvény feladata egy sides oldalú "kocka" eldobása. A sides lehetséges
értékei: 2, 3, 4, 6, 8, 10, 12, 20, és 100. Más értékekre a függvény egy
ValueError-t dob.
"""
def throw_one_dice(sides):
    return random.randint(1, sides)

"""
A függvény feladata a specifikációnak megfelelő számú kockadobás a megfelelő
típusú kockával. A specifikáció egy sztring, melynek alakja "<n>d<s>", ahol
<n> az eldobandó kockák darabszámát, <s> pedig egy kocka oldalszámát jelöli.
2d8 például két darab 8 oldalú kocka eldobásának összege. Az <n> elhagyható,
mely esetben egy kockát dobunk el. A d<s> rész is elhagyható, ekkor az
eredmény fixen <n>. <n> (ha meg van adva) egy nemnegatív egész szám kell,
hogy legyen, vagy a függvény ValueError-t dob.
"""
def throw_one_type(spec):
    n, d = spec.split('d')
    return sum(throw_one_dice(int(d)) for _ in range(int(n)))

"""
A függvény feladata vegyes kockadobások összegének szimulálása. A
dobássorozat specifikációja "<n1>d<s1>+<n2>d<s2>+...+<nk>d<sk>", ahol az
"<ni>d<si>" rész egy adott típusú kockával végzett dobássorozat
specifikációja. Az "<ni>" illetve "d<si>" részek külön-külön elhagyhatók.
"""
def throw(spec):
    return sum(throw_one_type(d) for d in spec.split('+'))

def main():
    while s := input('? '):
        try:
            print(f"{s} = {throw(s)}")
        except ValueError:
            print(f"Hibás specifikáció: {s}")

if __name__ == '__main__':
    main()

Adott továbbá a test/ mappában két fájl:

test/conftest.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
"""
Szoftverfesztelési folyamatok példaprogram
SZTE TTIK, Informatikai Intézet, Szoftverfejlesztés Tanszék
cc-by-nc-nd
"""

import pytest

# import sys, os
# sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../src'))

def pytest_runtest_setup(item):
    pass

def pytest_runtest_teardown(item):
    pass
test/test_dice.py
1
2
3
4
5
6
7
"""
Szoftverfesztelési folyamatok példaprogram
SZTE TTIK, Informatikai Intézet, Szoftverfejlesztés Tanszék
cc-by-nc-nd
"""

import dice

Készíts teszteket a függvények tesztelésére az src melletti test könyvtárba úgy, hogy azok a python -m pytest paranccsal futtathatóak legyenek!

Feladat: készíts teszteket a chess modulhoz

Adott a következő -- fejlesztés alatt álló, nem kész -- chess python package:

chess/init.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
"""
Szoftverfesztelési folyamatok példaprogram
SZTE TTIK, Informatikai Intézet, Szoftverfejlesztés Tanszék
cc-by-nc-nd

A chess package __init__.py fájlja.
"""

from . import constants
from . import board
from . import figures
chess/board.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
"""
Szoftverfesztelési folyamatok példaprogram
SZTE TTIK, Informatikai Intézet, Szoftverfejlesztés Tanszék
cc-by-nc-nd

A chess package board modulja.
"""

from . import constants

from rich.console import Console

"""
Új tábla létrehozása, melyen a bábuk a kezdőállásnak megfelelően állnak.
"""
def new_default_table():
    return [
        [{'fig':constants.FROOK, 'col':constants.CLGT},{'fig':constants.FPAWN, 'col':constants.CLGT},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':constants.FPAWN, 'col':constants.CDRK},{'fig':constants.FROOK, 'col':constants.CDRK}],
        [{'fig':constants.FKNGT, 'col':constants.CLGT},{'fig':constants.FPAWN, 'col':constants.CLGT},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':constants.FPAWN, 'col':constants.CDRK},{'fig':constants.FKNGT, 'col':constants.CDRK}],
        [{'fig':constants.FBSHP, 'col':constants.CLGT},{'fig':constants.FPAWN, 'col':constants.CLGT},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':constants.FPAWN, 'col':constants.CDRK},{'fig':constants.FBSHP, 'col':constants.CDRK}],
        [{'fig':constants.FQUEN, 'col':constants.CLGT},{'fig':constants.FPAWN, 'col':constants.CLGT},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':constants.FPAWN, 'col':constants.CDRK},{'fig':constants.FQUEN, 'col':constants.CDRK}],
        [{'fig':constants.FKING, 'col':constants.CLGT},{'fig':constants.FPAWN, 'col':constants.CLGT},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':constants.FPAWN, 'col':constants.CDRK},{'fig':constants.FKING, 'col':constants.CDRK}],
        [{'fig':constants.FBSHP, 'col':constants.CLGT},{'fig':constants.FPAWN, 'col':constants.CLGT},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':constants.FPAWN, 'col':constants.CDRK},{'fig':constants.FBSHP, 'col':constants.CDRK}],
        [{'fig':constants.FKNGT, 'col':constants.CLGT},{'fig':constants.FPAWN, 'col':constants.CLGT},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':constants.FPAWN, 'col':constants.CDRK},{'fig':constants.FKNGT, 'col':constants.CDRK}],
        [{'fig':constants.FROOK, 'col':constants.CLGT},{'fig':constants.FPAWN, 'col':constants.CLGT},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':constants.FPAWN, 'col':constants.CDRK},{'fig':constants.FROOK, 'col':constants.CDRK}]
    ]

"""
Új, üres tábla létrehozása.
"""
def new_empty_table():
    return [
        [{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None}],
        [{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None}],
        [{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None}],
        [{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None}],
        [{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None}],
        [{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None}],
        [{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None}],
        [{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None},{'fig':None, 'col':None}]
    ]

"""
A kapott tábla és a rajta lévő állás kirajzolása a konzolra.
"""
def print_board(board, con=Console()):
    con.print("   A B C D E F G H  ", style="bold cyan on black")
    for r in range(7, -1, -1):
        con.print(f"{r+1} ", style="bold cyan on black", end='')
        for c in range(0, 8):
            black = (r + c) % 2
            samec = board[c][r]['col'] == (constants.CDRK if black else constants.CLGT)
            cc = 'black' if black else 'white'
            fc = 'white' if black else 'black'
            match board[c][r]['fig']:
                case constants.FPAWN:
                    fg = f"{constants.CSPAWN if samec else constants.CIPAWN} "
                case constants.FKNGT:
                    fg = f"{constants.CSKNGT if samec else constants.CIKNGT} "
                case constants.FBSHP:
                    fg = f"{constants.CSBSHP if samec else constants.CIBSHP} "
                case constants.FROOK:
                    fg = f"{constants.CSROOK if samec else constants.CIROOK} "
                case constants.FQUEN:
                    fg = f"{constants.CSQUEN if samec else constants.CIQUEN} "
                case constants.FKING:
                    fg = f"{constants.CSKING if samec else constants.CIKING} "
                case _:
                    fg = '  '
            con.print(f"{fg}", style=f"{fc} on {cc}", end='')
        con.print(f" {r+1}", style="bold cyan on black")
    con.print("  A B C D E F G H", style="bold cyan on black")
chess/constants.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
"""
Szoftverfesztelési folyamatok példaprogram
SZTE TTIK, Informatikai Intézet, Szoftverfejlesztés Tanszék
cc-by-nc-nd

A chess package contants modulja.

A sakk megvalósításában használt konstansok:

F....  : A táblán egy figura
C...   : A táblán egy figura színe
CS.... : A konzolra kirajzolandó karakter, ha a mező és a figura színe egyezik
CI.... : A konzolra kirajzolandó karakter, ha a mező és a figura színe eltér
"""

FPAWN = 1
FKNGT = 2
FBSHP = 3
FROOK = 4
FQUEN = 5
FKING = 6

CLGT = 11
CDRK = 12

CSKING = '♔'
CSQUEN = '♕'
CSROOK = '♖'
CSBSHP = '♗'
CSKNGT = '♘'
CSPAWN = '♙'
CIKING = '♚'
CIQUEN = '♛'
CIROOK = '♜'
CIBSHP = '♝'
CIKNGT = '♞'
CIPAWN = '♟'
chess/figures.py
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
"""
Szoftverfesztelési folyamatok példaprogram
SZTE TTIK, Informatikai Intézet, Szoftverfejlesztés Tanszék
cc-by-nc-nd

A chess package figures modulja.

A modul legfőbb feladata (egyelőre) az egyes bábukhoz tartozó helyes lépések ellenőrzése.
"""

from . import constants

"""
Az aktuális ellenfél színe.
"""
def opponent(ply):
    constants.CDRK if ply == constants.CLGT else constants.CLGT

"""
Egy mező fenyegetve van-e a ply játékos valamely bábuja által.
TODO
"""
def threatened_by(pos, ply):
    return False

"""
Sakktábla pozíció (pl. 'c6') koordinátákká konvertálása (pl. (2,5)).
"""
def p2c(pos):
    c, r = pos
    if 'a' <= c <= 'h':
        c = ord(c) - ord('a')
    else:
        raise ValueError(f"Wrong column: {c}")
    if '1' <= r <= '8':
        r = ord(r) - ord('1')
    else:
        raise ValueError(f"Wrong row: {r}")
    return c, r

"""
Koordináták (pl. 2, 5) sakktábla pozícióvá (pl. 'c6') konvertálása.
"""
def c2p(c, r):
    return f"{chr(c+ord('a'))}{chr(r+ord('1'))}"

"""
Segédfüggvény, egy szám előjele.
"""
def sign(val):
    return 1 if val > 0 else -1 if val < 0 else 0

"""
Gyalog mozgása helyes-e?
A világos gyalog 2->8 irányban, a sötét gyalog 7->1 irányban tud mozogni.
- A gyalog egyet léphet előre szabad mezőre.
- A kezdősorból (2. a világosnak és 7. a sötétnek) kettőt is előreléphet szabad mezőre, ilyenkor
  az ellenfélnek en-passant-ra van lehetősége az "átugrott", szintén üres mezőn, így ezt a mezőt kell visszaadni.
- A gyalog átlósan előre egyet lépve ütheti az ellenfél ott álló bábuját.
- En-passant lehetőség esetén a gyalog egyet átlósan előre lépve a megadott üres mezőre érkezhet.
"""
def valid_move_pawn(board, spos, epos, *, enpassant=None):
    sc, sr = p2c(spos)
    ec, er = p2c(epos)
    if board[sc][sr]['fig'] != constants.FPAWN:
        return False
    if sc == ec:
        if board[sc][sr]['col'] == constants.CLGT:
            if board[sc][sr+1]['fig'] is None:
                if er == sr+1:
                    return True
                if sr == 2 and er == 4 and board[sc][er]['fig'] is None:
                    return c2p(sc, 3)
        else:
            if board[sc][sr-1]['fig'] is None:
                if er == sr-1:
                    return True
                elif er == 7 and er == 5 and board[sc][er]['fig'] is None:
                    return c2p(sc, 6)
        return False
    if ec != sc-1 and ec != sc+1:
        return False
    if board[sc][sr]['col'] == constants.CLGT:
        if er == sr+1 and board[ec][er]['fig'] is not None and board[sc][sr]['col'] == constants.CDRK:
            return True
        return epos == enpassant
    else:
        if er == sr-1 and board[ec][er]['fig'] is not None and board[sc][sr]['col'] == constants.CLGT:
            return True
        return epos == enpassant
    return False

"""
Huszár mozgása helyes-e?
A huszár egyik irányba kettőt, másik irányba egyet mozdulva léphet vagy üthet, függetlenül attól, hogy
volt-e az útjában másik bábu.
"""
def valid_move_knight(board, spos, epos):
    sc, sr = p2c(spos)
    ec, er = p2c(epos)
    if board[sc][sr]['fig'] != constants.FKNGT:
        return False
    return ((abs(sc-ec) == 1 and abs(sr-er) == 2) or (abs(sc-ec) == 2 and abs(sr-er) == 1))

"""
A futó átlósan (mindig azonos színű mezőn) mozogva léphet vagy üthet, de bábut nem ugorhat át.
"""
def valid_move_bishop(board, spos, epos):
    sc, sr = p2c(spos)
    ec, er = p2c(epos)
    if board[sc][sr]['fig'] != constants.FBSHP:
        return False
    if abs(sc-ec) != abs(sr-er):
        return False
    dc, dr = sign(ec-sc), sign(er-sr)
    for i in range(1, abs(max(ec-sc, er-sr))):
        if board[sc + dc * i][sr + dr * i]['fig'] is not None:
            return False
    return True

"""
A bástya sorban vagy oszlopban egyenesen mozogva léphet vagy üthet, de bábut nem ugorhat át.
"""
def valid_move_rook(board, spos, epos):
    sc, sr = p2c(spos)
    ec, er = p2c(epos)
    if board[sc][sr]['fig'] != constants.FROOK:
        return False
    if sc != ec and sr != er:
        return False
    dc, dr = sign(ec-sc), sign(er-sr)
    for i in range(1, max(abs(ec-sc), abs(er-sr))):
        if board[sc + dc * i][sr + dr * i]['fig'] is not None:
            return False
    return True

"""
A vezér futóként vagy bástyaként, azaz átlósan, sorban vagy oszlopban mozoghat vagy üthet,
de bábut nem ugorhat át.
"""
def valid_move_queen(board, spos, epos):
    sc, sr = p2c(spos)
    ec, er = p2c(epos)
    if board[sc][sr]['fig'] != constants.FQUEN:
        return False
    if sc != ec and sr != er and abs(sc-ec) != abs(sr-er):
        return False
    dc, dr = sign(ec-sc), sign(er-sr)
    for i in range(1, abs(max(ec-sc, er-sr))):
        if board[sc + dc * i][sr + dr * i]['fig'] is not None:
            return False
    return True

"""
A kirány a 8 szomszédos mező valamelyikére léphet, ha azt nem fenyegeti az ellenfél egyetlen bábuja sem.
"""
def valid_move_king(board, spos, epos):
    sc, sr = p2c(spos)
    ec, er = p2c(epos)
    if board[sc][sr]['fig'] != constants.FKING:
        return False
    if abs(sc-ec) > 1 or abs(sr-er) > 1 or (sc == ec and sr == er):
        return False
    if threatened_by(epos, opponent(board[sc][sr]['col'])):
        return False
    return True

"""
A sáncoláskor, ha sem a király, sem a sáncoláshoz használt bástya nem mozdult még el
a kiinduló helyéről a játék során, és a kettő között minden mező üres, és sem a királyt,
sem a mellette az adott bástya irányában lévő két mezőt nem fenyegeti az ellenfél, akkor
A királyt két mezővel a bástya felé mozgathatjuk, a bástya pedig a királyt átugorva a
király által "átlépett" mezőre kerül.
"""
def valid_move_castling(board, spos, epos, *, king_moved=True, rook_a_moved=True, rook_h_moved=True):
    sc, sr = p2c(spos)
    ec, er = p2c(epos)
    if king_moved or rook_a_moved or rook_h_moved or sc != 5 or sr != 1 or sr != 8 or sr != er or board[sc][sr]['fig'] != constants.FKING or board[ec][sr]['fig'] is not None or threatened_by(c2p(ec, er), opponent(board[sc][sr]['col'])):
        return False
    if ec == 7:
        return board[6][sr]['fig'] is None and not threatened_by(c2p(6, sr), opponent(board[sc][sr]['col'])) and board[8][sr]['col'] == board[sc][sr]['col'] and board[8][sr]['fig'] == constants.FROOK
    elif ec == 3:
        return board[4][sr]['fig'] is None and not threatened_by(c2p(4, sr), opponent(board[sc][sr]['col'])) and board[1][sr]['col'] == board[sc][sr]['col'] and board[1][sr]['fig'] == constants.FROOK
    return False

Adott továbbá a csomaghoz pár kezdeti teszt:

test/test_figures.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
"""
Szoftverfesztelési folyamatok példaprogram
SZTE TTIK, Informatikai Intézet, Szoftverfejlesztés Tanszék
cc-by-nc-nd

A chess package figures moduljának egységtesztjei.
"""

import chess

def test_c2p():
    assert chess.figures.c2p(0, 0) == "a1"
    assert chess.figures.c2p(7, 7) == "h8"

def test_p2c():
    assert chess.figures.p2c("a8") == (0,7)
    assert chess.figures.p2c("h1") == (7,0)

def test_valid_move_rook_valid_free_col():
    table = chess.board.new_empty_table()
    table[3][3]= {'fig': chess.constants.FROOK, 'col': chess.constants.CLGT}
    assert chess.figures.valid_move_rook(table, 'd4', 'd6')

def test_valid_move_rook_valid_free_row():
    table = chess.board.new_empty_table()
    table[3][3]= {'fig': chess.constants.FROOK, 'col': chess.constants.CLGT}
    assert chess.figures.valid_move_rook(table, 'd4', 'b4')

def test_valid_move_rook_invalid_free():
    table = chess.board.new_empty_table()
    table[3][3]= {'fig': chess.constants.FROOK, 'col': chess.constants.CLGT}
    assert chess.figures.valid_move_rook(table, 'd4', 'g6') is False

def test_valid_move_rook_valid_capture():
    table = chess.board.new_empty_table()
    table[3][3]= {'fig': chess.constants.FROOK, 'col': chess.constants.CLGT}
    table[3][6]= {'fig': chess.constants.FROOK, 'col': chess.constants.CDRK}
    assert chess.figures.valid_move_rook(table, 'd4', 'd7')

def test_valid_move_rook_invalid_cannot_capture_self():
    table = chess.board.new_empty_table()
    table[3][3]= {'fig': chess.constants.FROOK, 'col': chess.constants.CLGT}
    table[3][6]= {'fig': chess.constants.FROOK, 'col': chess.constants.CLGT}
    assert chess.figures.valid_move_rook(table, 'd4', 'd7') is False
def test_valid_move_rook_invalid_blocked_path():
    table = chess.board.new_empty_table()
    table[3][3]= {'fig': chess.constants.FROOK, 'col': chess.constants.CLGT}
    table[3][6]= {'fig': chess.constants.FROOK, 'col': chess.constants.CLGT}
    assert chess.figures.valid_move_rook(table, 'd4', 'd8') is False

Először futtasd a teszteket a python -m pytest paranccsal! Milyen eredménnyel futottak a tesztek?

Készíts további teszteket a chess.figures modul függvényeinek tesztelésére! Próbáld meg kijavítani a modult, ha a tesztek alapján hibás!