Skip to content

Commit f477438

Browse files
committed
[tests] Rewrite entire test suite using pytest
1 parent a223c72 commit f477438

File tree

9 files changed

+241
-131
lines changed

9 files changed

+241
-131
lines changed

pyproject.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,9 @@ path = "src/xpp/__init__.py"
5050

5151
[tool.hatch.build.targets.wheel]
5252
packages = ["src/xpp", "src/caffeine"]
53+
54+
[tool.pytest.ini_options]
55+
addopts = [
56+
"--import-mode=importlib",
57+
]
58+
pythonpath = "src"

src/tests/__init__.py

Lines changed: 58 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,61 @@
1+
# Copyright (c) 2024 iiPython
2+
13
# Modules
2-
from rich import print as rp
3-
from rich.table import Table
4+
from typing import Any, List
45
from types import FunctionType
56

6-
# Load xpp
7-
from xpp import Interpreter
8-
from xpp.core.sections import Section
9-
10-
# Fake out the x++ interpreter
11-
inter = Interpreter("_tests.xpp", [])
12-
section = Section("_tests.main", "", [], 1, [])
13-
section.initialize(inter.memory)
14-
inter.stack.append(section)
15-
16-
# Start running x++ code
17-
def start_tests(name: str, tests: list) -> None:
18-
table = Table(title = f"x++ {name} Test Results")
19-
[table.add_column(c) for c in ["Expression", "x++", "Expected", "Result"]]
20-
for test in tests:
21-
try:
22-
resp = inter.execute(test[0])
23-
24-
except Exception as e:
25-
resp = type(e).__name__
26-
27-
isf = isinstance(test[1], FunctionType)
28-
table.add_row(
29-
str(test[0]),
30-
str(resp),
31-
str(test[1] if not isf else "<Function>"),
32-
"[green]✓ PASS[/]" if (test[1]() if isf else (resp == test[1])) else "[red]✕ FAIL[/]"
33-
)
34-
35-
rp(table)
7+
# Fake classes
8+
class FakeDatastore():
9+
def __init__(self, value: Any) -> None:
10+
self.raw, self.value = value, value
11+
self.deleted = False
12+
13+
def set(self, value: Any) -> None:
14+
self.value = value
15+
16+
def delete(self) -> None:
17+
self.deleted = True
18+
19+
def refresh(self) -> None:
20+
if isinstance(self.value, bool):
21+
self.value = not self.value
22+
23+
class FakeSection():
24+
def __init__(self) -> None:
25+
self.active = True
26+
self.return_value = []
27+
28+
class FakeInterpreter():
29+
def __init__(self) -> None:
30+
self.stack = [FakeSection()]
31+
self.recently_executed = []
32+
33+
def execute(self, data: Any) -> None:
34+
if data == "_RAISE":
35+
raise ValueError
36+
37+
self.recently_executed.append(data)
38+
39+
def run_section(self, section: str, args: List[Any]) -> List[Any]:
40+
return args
41+
42+
class FakeMemory():
43+
def __init__(self) -> None:
44+
self.interpreter = FakeInterpreter()
45+
self.variables = {}
46+
47+
# Initialization
48+
global_mem = FakeMemory()
49+
50+
# Handle running
51+
def run(function: FunctionType, args: List[Any]) -> Any:
52+
args = [
53+
FakeDatastore(a) if not isinstance(a, FakeDatastore) else a
54+
for a in args
55+
]
56+
return function(global_mem, args)
57+
58+
def full_evaluate(function: FunctionType, args: List[Any], expect: Any) -> None:
59+
output = FakeDatastore("?")
60+
assert run(function, args + [output]) == expect
61+
assert output.value == expect

src/tests/test_compare.py

Lines changed: 0 additions & 21 deletions
This file was deleted.

src/tests/test_file.py

Lines changed: 0 additions & 37 deletions
This file was deleted.

src/tests/test_fileio.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Copyright (c) 2024 iiPython
2+
3+
# Modules
4+
import os
5+
from pathlib import Path
6+
7+
from xpp.modules.ops.stdlib.fileio import XOperators
8+
9+
from . import run
10+
11+
# Begin test definitions
12+
def test_load():
13+
Path("_xpp.test").write_text("hello, world!")
14+
assert run(XOperators.load, ["_xpp.test"]) == "hello, world!"
15+
os.remove("_xpp.test")
16+
17+
def test_save():
18+
run(XOperators.save, ["_xpp.test", "hello, world!"])
19+
assert Path("_xpp.test").read_text() == "hello, world!"
20+
os.remove("_xpp.test")

src/tests/test_internal.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Copyright (c) 2024 iiPython
2+
3+
# Modules
4+
from xpp.modules.ops.stdlib.internal import XOperators
5+
6+
from . import run, global_mem, FakeDatastore
7+
8+
# Begin test definitions
9+
def test_evl():
10+
run(XOperators.evl, ["mem.variables['_test'] = True"])
11+
assert global_mem.variables.get("_test") is True
12+
13+
def test_if():
14+
run(XOperators.if_, [True, "_1"])
15+
assert global_mem.interpreter.recently_executed[-1] == "_1"
16+
run(XOperators.if_, [False, "_2"])
17+
assert global_mem.interpreter.recently_executed[-1] == "_1"
18+
run(XOperators.if_, [False, "_3", True, "_4"])
19+
assert global_mem.interpreter.recently_executed[-1] == "_4"
20+
run(XOperators.if_, [True, "_5", False, "_6"])
21+
assert global_mem.interpreter.recently_executed[-1] == "_5"
22+
23+
def test_jmp():
24+
assert run(XOperators.jmp, ["_", "a", 1, .25, True]) == ["a", 1, .25, True]
25+
26+
def test_rem():
27+
variable = FakeDatastore("hello world")
28+
run(XOperators.rem, [variable])
29+
assert variable.deleted is True
30+
31+
def test_ret():
32+
run(XOperators.ret, [1, 2])
33+
assert global_mem.interpreter.stack[-1].active is False
34+
assert global_mem.interpreter.stack[-1].return_value == [1, 2]
35+
36+
def test_rep():
37+
run(XOperators.rep, [5, "ooga booga"])
38+
assert global_mem.interpreter.recently_executed[-5:] == ["ooga booga"] * 5
39+
40+
def test_try():
41+
run(XOperators.try_, ["_RAISE"])
42+
assert global_mem.interpreter.recently_executed[-1] != "_RAISE"
43+
44+
run(XOperators.try_, ["_RAISE", "_try"])
45+
assert global_mem.interpreter.recently_executed[-1] == "_try"
46+
47+
def test_var():
48+
variable = FakeDatastore(None)
49+
run(XOperators.var, [variable, "hello world"])
50+
assert variable.value == "hello world" and variable.raw is None
51+
52+
def test_whl():
53+
variable = FakeDatastore(True)
54+
run(XOperators.whl, [variable, "whip and nae nae"])
55+
assert variable.value is False and global_mem.interpreter.recently_executed[-1] == "whip and nae nae"

src/tests/test_math.py

Lines changed: 36 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,38 @@
1-
# Copyright 2023-2024 iiPython
1+
# Copyright (c) 2024 iiPython
22

33
# Modules
4-
import sys
5-
import pathlib
6-
sys.path.insert(1, str(pathlib.Path(__file__).parent.parent.resolve()))
7-
8-
# Start testing
9-
from tests import start_tests
10-
start_tests("Math", [
11-
12-
# Addition testing
13-
("add 2 3", 5),
14-
("add 0.1 0.2", .1 + .2),
15-
("add 0.25 (add 1 0.5)", 1.75),
16-
("add 2 (8 + 10)", 20),
17-
("add 1 (.1 + .2 + .3 + .4)", 2),
18-
("add (7 + 4 + (2 + (5 + 2))) (8 + 9 + 2)", 39),
19-
20-
# Subtraction testing
21-
("sub 2 3", -1),
22-
("sub 0.1 0.2", -.1),
23-
("sub 0.25 (sub 1 0.5)", -.25),
24-
("sub 2 (8 - 10)", 4),
25-
("sub 1 (.1 - .2 - .3 - .4)", 1.8),
26-
("sub (7 - 4 - (2 - (5 - 2))) (8 - 9 - 2)", 7),
27-
28-
# Multiplication testing
29-
("mul 2 3", 6),
30-
("mul 0.1 0.2", .1 * .2),
31-
("mul 0.25 (mul 1 0.5)", .125),
32-
("mul 2 (8 * 10)", 160),
33-
("mul 1 (.1 * .2 * .3 * .4)", .1 * .2 * .3 * .4),
34-
("mul (7 * 4 * (2 * (5 * 2))) (8 * 9 * 2)", 80640),
35-
36-
# Division testing
37-
("div 2 3", 2 / 3),
38-
("div 0.1 0.2", .1 / .2),
39-
("div 0.25 (div 1 0.5)", .125),
40-
("div 2 (8 / 10)", 2.5),
41-
("div 1 (.1 / .2 / .3 / .4)", .24),
42-
("div (7 / 4 / (2 / (5 / 2))) (8 / 9 / 2)", 4.921875),
43-
])
4+
from xpp.modules.ops.stdlib.math import XOperators
5+
6+
from . import run, full_evaluate
7+
8+
# Begin test definitions
9+
def test_add():
10+
full_evaluate(XOperators.add, [1, 2, 3], 6)
11+
12+
def test_dec():
13+
full_evaluate(XOperators.dec, [5], 4)
14+
15+
def test_div():
16+
full_evaluate(XOperators.div, [1, 2], .5)
17+
18+
def test_inc():
19+
full_evaluate(XOperators.inc, [5], 6)
20+
21+
def test_mul():
22+
full_evaluate(XOperators.mul, [5, 3], 15)
23+
24+
def test_pow():
25+
full_evaluate(XOperators.pow, [5, 2], 25)
26+
27+
def test_rnd():
28+
full_evaluate(XOperators.rnd, [0.3], 0)
29+
full_evaluate(XOperators.rnd, [0.7], 1)
30+
full_evaluate(XOperators.rnd, [0.5666, 2], .57)
31+
full_evaluate(XOperators.rnd, [0.203, 3], .203)
32+
33+
def test_rng():
34+
assert isinstance(run(XOperators.rng, [1, 5]), int)
35+
full_evaluate(XOperators.rng, [1, 1], 1)
36+
37+
def test_sub():
38+
full_evaluate(XOperators.sub, [1, 2], -1)

src/tests/test_objects.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Copyright (c) 2024 iiPython
2+
3+
# Modules
4+
from xpp.modules.ops.stdlib.objects import XOperators
5+
6+
from . import run, full_evaluate, FakeDatastore
7+
8+
# Begin test definitions
9+
def test_new():
10+
assert isinstance(run(XOperators.new, ["list"]), list)
11+
assert isinstance(run(XOperators.new, ["dict"]), dict)
12+
13+
full_evaluate(XOperators.new, ["list"], [])
14+
full_evaluate(XOperators.new, ["dict"], {})
15+
16+
def test_psh():
17+
variable = FakeDatastore([1, 2])
18+
run(XOperators.psh, [variable, 3])
19+
assert variable.value == [1, 2, 3]
20+
21+
def test_pop():
22+
full_evaluate(XOperators.pop, [[1, 2, 3]], 3)
23+
24+
def test_get():
25+
full_evaluate(XOperators.get, [{"a": 5}, "a"], 5)
26+
27+
def test_set():
28+
variable = FakeDatastore({"a": 5})
29+
assert variable.value["a"] == 5
30+
run(XOperators.set_, [variable, "a", 6])
31+
assert variable.value["a"] == 6
32+

src/tests/test_strman.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Copyright (c) 2024 iiPython
2+
3+
# Modules
4+
from xpp.modules.ops.stdlib.strman import XOperators
5+
6+
from . import run, full_evaluate
7+
8+
# Begin test definitions
9+
def test_chr():
10+
full_evaluate(XOperators.chr_, ["hello", 0], "h")
11+
full_evaluate(XOperators.chr_, ["hello", 0, 2], "hel")
12+
13+
def test_flt():
14+
full_evaluate(XOperators.flt_, ["0.5"], 0.5)
15+
full_evaluate(XOperators.flt_, ["-0.5"], -0.5)
16+
17+
def test_idx():
18+
full_evaluate(XOperators.idx, ["hello world", "world"], 6)
19+
20+
def test_int():
21+
full_evaluate(XOperators.int_, ["5"], 5)
22+
23+
def test_len():
24+
full_evaluate(XOperators.len_, ["hello"], 5)
25+
26+
def test_lwr():
27+
full_evaluate(XOperators.lwr, ["HELLO"], "hello")
28+
29+
def test_str():
30+
assert run(XOperators.str_, [1]) == "1"
31+
assert run(XOperators.str_, [0.5]) == "0.5"
32+
33+
def test_upr():
34+
full_evaluate(XOperators.upr, ["hello"], "HELLO")

0 commit comments

Comments
 (0)