mirror of
https://github.com/senju1337/senju.git
synced 2025-12-23 23:39:27 +00:00
Merge pull request #39 from senju1337/test/OPS-70
Add more tests for the haiku and store manager classes
This commit is contained in:
commit
bf3f70ed2f
6 changed files with 142 additions and 43 deletions
25
poetry.lock
generated
25
poetry.lock
generated
|
|
@ -1,4 +1,4 @@
|
|||
# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand.
|
||||
# This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "alabaster"
|
||||
|
|
@ -25,7 +25,7 @@ files = [
|
|||
]
|
||||
|
||||
[package.extras]
|
||||
dev = ["backports.zoneinfo ; python_version < \"3.9\"", "freezegun (>=1.0,<2.0)", "jinja2 (>=3.0)", "pytest (>=6.0)", "pytest-cov", "pytz", "setuptools", "tzdata ; sys_platform == \"win32\""]
|
||||
dev = ["backports.zoneinfo", "freezegun (>=1.0,<2.0)", "jinja2 (>=3.0)", "pytest (>=6.0)", "pytest-cov", "pytz", "setuptools", "tzdata"]
|
||||
|
||||
[[package]]
|
||||
name = "blinker"
|
||||
|
|
@ -255,7 +255,7 @@ files = [
|
|||
]
|
||||
|
||||
[package.extras]
|
||||
toml = ["tomli ; python_full_version <= \"3.11.0a6\""]
|
||||
toml = ["tomli"]
|
||||
|
||||
[[package]]
|
||||
name = "docutils"
|
||||
|
|
@ -514,6 +514,21 @@ tomli = {version = ">=1", markers = "python_version < \"3.11\""}
|
|||
[package.extras]
|
||||
dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
|
||||
|
||||
[[package]]
|
||||
name = "pytest-httpserver"
|
||||
version = "1.1.2"
|
||||
description = "pytest-httpserver is a httpserver for pytest"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "pytest_httpserver-1.1.2-py3-none-any.whl", hash = "sha256:93009d79574fc982301e8494fdea0884f21bb0caf3bcc719151dfbd1e3a943ea"},
|
||||
{file = "pytest_httpserver-1.1.2.tar.gz", hash = "sha256:38d0b726580d05c47cbd0ced1ecb36a51668ef1596cdc6d70a9cfa2b3cc00ebd"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
Werkzeug = ">=2.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.32.3"
|
||||
|
|
@ -752,7 +767,7 @@ files = [
|
|||
]
|
||||
|
||||
[package.extras]
|
||||
brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""]
|
||||
brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
|
||||
h2 = ["h2 (>=4,<5)"]
|
||||
socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
|
||||
zstd = ["zstandard (>=0.18.0)"]
|
||||
|
|
@ -778,4 +793,4 @@ watchdog = ["watchdog (>=2.3)"]
|
|||
[metadata]
|
||||
lock-version = "2.1"
|
||||
python-versions = ">=3.10"
|
||||
content-hash = "ce9cac7092447dc5d6b3920853bb10fcc166018bc4f48c50925ef09db74e7891"
|
||||
content-hash = "76f74a5c2443d5c8e9db9433f0bdcc94a1d12c469f8b49dd325f3cc5a1b06f4e"
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ dependencies = [
|
|||
"tinydb (>=3.1.0,<4.0.0)",
|
||||
"requests (>=2.32.3,<3.0.0)",
|
||||
"coverage (>=7.6.12,<8.0.0)",
|
||||
"pytest-httpserver (>=1.1.2,<2.0.0)",
|
||||
]
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ class Haiku:
|
|||
return json.dumps(self.lines)
|
||||
|
||||
@staticmethod
|
||||
def request_haiku(seed: str) -> Haiku:
|
||||
def request_haiku(seed: str, url=AI_BASE_URL + AI_GEN_ENDPOINT) -> Haiku:
|
||||
"""This function prompts the ai to generate
|
||||
the hauku based on the user input"""
|
||||
|
||||
|
|
@ -29,23 +29,32 @@ class Haiku:
|
|||
"eval_count": 20
|
||||
}
|
||||
|
||||
tries = 0
|
||||
while True:
|
||||
tries += 1
|
||||
try:
|
||||
r = requests.post(url=AI_BASE_URL + AI_GEN_ENDPOINT,
|
||||
r = requests.post(url=url,
|
||||
json=ai_gen_request)
|
||||
ai_response = str(r.json()["response"])
|
||||
|
||||
logging.warning(ai_response)
|
||||
logging.debug(f"ai response: {ai_response}")
|
||||
|
||||
lines = ai_response.split("\n")
|
||||
|
||||
while len(lines) != 3:
|
||||
lines.pop()
|
||||
|
||||
logging.warning(lines)
|
||||
logging.info(f"lines for haiku: {lines}")
|
||||
|
||||
if len(lines) != 3:
|
||||
continue
|
||||
if len(lines) < 3:
|
||||
if tries < 20:
|
||||
logging.warning("too few lines, trying again")
|
||||
logging.debug(lines)
|
||||
continue
|
||||
else:
|
||||
logging.warning("too many tries, aborting")
|
||||
raise Exception(
|
||||
"Generating the haiku took too many tries")
|
||||
|
||||
haiku = Haiku(
|
||||
[
|
||||
|
|
@ -55,8 +64,9 @@ class Haiku:
|
|||
])
|
||||
|
||||
break
|
||||
except json.JSONDecodeError:
|
||||
continue
|
||||
except json.JSONDecodeError as e:
|
||||
logging.error(f"error while reading json from LLM: {e}")
|
||||
raise e
|
||||
|
||||
return haiku
|
||||
|
||||
|
|
|
|||
68
tests/test_haiku.py
Normal file
68
tests/test_haiku.py
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
# I do not trust python and it's tests, so I'm testing them. May not be worth
|
||||
# much, but at least it shows me a few things.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pytest_httpserver import HTTPServer
|
||||
import requests
|
||||
|
||||
# do not remove this import. This is needed for
|
||||
# pytest fixtures to work
|
||||
import pytest # noqa: F401
|
||||
|
||||
from senju.haiku import Haiku # noqa: F401
|
||||
|
||||
# Note: these weird arguments are an indicator of what should be dome
|
||||
# before. For example, `temp_data_dir` is a function in `conftest.py`. If we
|
||||
# put it in the arguments, it seems to run before our test, and the return
|
||||
# value becomes a local. This is all very confusing for someone used to
|
||||
# Rust's libtest
|
||||
|
||||
|
||||
def test_create_haiku():
|
||||
haiku = Haiku(["line number 1", "line number 2", "line number 3"])
|
||||
assert haiku.lines[0] == "line number 1"
|
||||
assert haiku.lines[1] == "line number 2"
|
||||
assert haiku.lines[2] == "line number 3"
|
||||
assert len(haiku.lines) == 3
|
||||
|
||||
|
||||
def test_get_haiku_json():
|
||||
haiku = Haiku(["line number 1", "line number 2", "line number 3"])
|
||||
data_raw: str = haiku.get_json()
|
||||
assert data_raw == '["line number 1", "line number 2", "line number 3"]'
|
||||
data = json.loads(data_raw)
|
||||
assert haiku.lines[0] == "line number 1"
|
||||
assert haiku.lines[1] == "line number 2"
|
||||
assert haiku.lines[2] == "line number 3"
|
||||
assert len(haiku.lines) == 3
|
||||
assert data == ['line number 1', 'line number 2', 'line number 3']
|
||||
|
||||
|
||||
def test_request_haiku(httpserver: HTTPServer):
|
||||
|
||||
httpserver.expect_request(
|
||||
"/testhaiku").respond_with_json({"response":
|
||||
"The apparition of these\n"
|
||||
"faces in a crowd; Petal\n"
|
||||
"on a wet, black bough."
|
||||
})
|
||||
|
||||
haiku = Haiku.request_haiku(
|
||||
"apple banana papaya", url=httpserver.url_for("/testhaiku"))
|
||||
assert haiku.lines[0] == "The apparition of these"
|
||||
assert haiku.lines[1] == "faces in a crowd; Petal"
|
||||
assert haiku.lines[2] == "on a wet, black bough."
|
||||
assert len(haiku.lines) == 3
|
||||
|
||||
|
||||
def test_request_haiku_respondse_bad(httpserver: HTTPServer):
|
||||
with pytest.raises(requests.exceptions.JSONDecodeError):
|
||||
|
||||
httpserver.expect_request(
|
||||
"/testhaiku").respond_with_data(
|
||||
"this is completely wrong" + ("A" * 50 + "\n") * 20)
|
||||
|
||||
Haiku.request_haiku(
|
||||
"apple banana papaya", url=httpserver.url_for("/testhaiku"))
|
||||
|
|
@ -3,11 +3,21 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import pytest # noqa: F401
|
||||
import os
|
||||
|
||||
from senju.haiku import DEFAULT_HAIKU, Haiku
|
||||
from senju.store_manager import StoreManager # noqa: F401
|
||||
|
||||
|
||||
def test_temp_data_dir(temp_data_dir):
|
||||
print(temp_data_dir)
|
||||
testpath = temp_data_dir / "__test"
|
||||
with open(testpath, "w") as f:
|
||||
f.write("that dir actually works")
|
||||
os.remove(testpath)
|
||||
assert not os.path.exists(testpath)
|
||||
|
||||
|
||||
def test_save_and_load_any(store_manager: StoreManager):
|
||||
thing = {
|
||||
"color": "blue",
|
||||
|
|
@ -58,3 +68,28 @@ def test_load_latest_or_default_with_non_empty(temp_data_dir):
|
|||
haiku = store.load_haiku(store.get_id_of_latest_haiku())
|
||||
assert haiku != DEFAULT_HAIKU
|
||||
assert haiku == nonsense_test_haiku
|
||||
|
||||
|
||||
def test_load_latest_with_non_empty_store(temp_data_dir):
|
||||
store = StoreManager(temp_data_dir / "empty_store.json")
|
||||
store.save_haiku(Haiku(["hello", "world", "bananenkrokodil"]))
|
||||
h = store.get_id_of_latest_haiku()
|
||||
assert h is not None
|
||||
assert h > 0
|
||||
|
||||
|
||||
def test_create_store_with_bad_file(temp_data_dir):
|
||||
with pytest.raises(Exception):
|
||||
testpath = temp_data_dir / "non_empty.json"
|
||||
with open(testpath, "w") as f:
|
||||
f.write("BUT IT DOES NOT ACTUALLY HAVE JSON")
|
||||
store = StoreManager(testpath)
|
||||
store._save({"hello": 19})
|
||||
|
||||
|
||||
def test_create_store_with_non_empty(temp_data_dir):
|
||||
testpath = temp_data_dir / "non_empty.json"
|
||||
with open(testpath, "w") as f:
|
||||
f.write('{"this": ["is","valid","json"]}')
|
||||
store = StoreManager(testpath)
|
||||
store._save({"hello": 19})
|
||||
|
|
|
|||
|
|
@ -1,30 +0,0 @@
|
|||
# I do not trust python and it's tests, so I'm testing them. May not be worth
|
||||
# much, but at least it shows me a few things.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
|
||||
# do not remove this import. This is needed for
|
||||
# pytest fixtures to work
|
||||
import pytest # noqa: F401
|
||||
|
||||
import senju # noqa: F401
|
||||
|
||||
# Note: these weird arguments are an indicator of what should be dome
|
||||
# before. For example, `temp_data_dir` is a function in `conftest.py`. If we
|
||||
# put it in the arguments, it seems to run before our test, and the return
|
||||
# value becomes a local. This is all very confusing for someone used to
|
||||
# Rust's libtest
|
||||
|
||||
|
||||
def test_tests_are_loaded():
|
||||
assert True # if we make it here, they are
|
||||
|
||||
|
||||
def test_temp_data_dir(temp_data_dir):
|
||||
print(temp_data_dir)
|
||||
testpath = temp_data_dir / "__test"
|
||||
with open(testpath, "w") as f:
|
||||
f.write("that dir actually works")
|
||||
os.remove(testpath)
|
||||
Loading…
Add table
Add a link
Reference in a new issue