import logging import pytest from unittest.mock import Mock from appengine import AppEngine @pytest.fixture def app(): ae = AppEngine("test_app") ae.cl = Mock() # prevent NoneType error in wait_stop before exec() is called yield ae ae.stop() ae.stop_thread.join(timeout=2) class TestInit: def test_creates_logger(self, app): assert isinstance(app.log, logging.Logger) def test_log_level_warning_by_default(self, app): assert app.log.level == logging.WARNING def test_log_level_debug_when_requested(self): ae = AppEngine("test_debug", debug=True) ae.cl = Mock() assert ae.log.level == logging.DEBUG ae.stop() ae.stop_thread.join(timeout=2) def test_stop_thread_is_alive(self, app): assert app.stop_thread.is_alive() class TestParseConfig: def test_valid_config_file(self, tmp_path): cf = tmp_path / "config.ini" cf.write_text("[general]\ndefault = mymod\n") ae = AppEngine("test_cfg") ae.cl = Mock() ae.parse_config(str(cf)) assert ae.conf["general"]["default"] == "mymod" ae.stop() ae.stop_thread.join(timeout=2) def test_missing_config_raises(self, app): with pytest.raises(Exception, match="not found"): app.parse_config("/nonexistent/config.ini") class TestDefLog: def test_valid_log_file_adds_file_handler(self, tmp_path): log_file = str(tmp_path / "test.log") ae = AppEngine("test_logfile", log_file=log_file) ae.cl = Mock() assert any(isinstance(h, logging.FileHandler) for h in ae.log.handlers) ae.stop() ae.stop_thread.join(timeout=2) for h in ae.log.handlers: h.close() class TestStop: def test_stop_sets_event(self, app): assert not app.stop_event.is_set() app.stop() assert app.stop_event.is_set() def test_stop_thread_exits_after_stop(self, app): app.stop() app.stop_thread.join(timeout=2) assert not app.stop_thread.is_alive()