Improved test architecture #139
This commit is contained in:
parent
de78cec96c
commit
75c316f2d2
@ -9,6 +9,7 @@ from cpl_core.dependency_injection import ServiceProviderABC, ServiceCollectionA
|
|||||||
from cpl_core.environment import ApplicationEnvironment
|
from cpl_core.environment import ApplicationEnvironment
|
||||||
from cpl_discord import get_discord_collection
|
from cpl_discord import get_discord_collection
|
||||||
from cpl_discord.discord_event_types_enum import DiscordEventTypesEnum
|
from cpl_discord.discord_event_types_enum import DiscordEventTypesEnum
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
from ui_tests.test_on_ready_event import TestOnReadyEvent
|
from ui_tests.test_on_ready_event import TestOnReadyEvent
|
||||||
|
|
||||||
@ -21,6 +22,7 @@ class Startup(StartupABC):
|
|||||||
self._config: Optional[ConfigurationABC] = None
|
self._config: Optional[ConfigurationABC] = None
|
||||||
|
|
||||||
def configure_configuration(self, configuration: ConfigurationABC, environment: ApplicationEnvironment) -> ConfigurationABC:
|
def configure_configuration(self, configuration: ConfigurationABC, environment: ApplicationEnvironment) -> ConfigurationABC:
|
||||||
|
load_dotenv()
|
||||||
configuration.add_environment_variables('KDB_TEST_')
|
configuration.add_environment_variables('KDB_TEST_')
|
||||||
configuration.add_environment_variables('DISCORD_')
|
configuration.add_environment_variables('DISCORD_')
|
||||||
|
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
from cpl_core.configuration import ConfigurationABC
|
from cpl_core.configuration import ConfigurationABC
|
||||||
from cpl_core.dependency_injection import ServiceProviderABC
|
from cpl_core.dependency_injection import ServiceProviderABC
|
||||||
from cpl_discord.application import DiscordBotApplicationABC
|
from cpl_discord.application import DiscordBotApplicationABC
|
||||||
|
from cpl_discord.configuration import DiscordBotSettings
|
||||||
from cpl_discord.service import DiscordBotServiceABC
|
from cpl_discord.service import DiscordBotServiceABC
|
||||||
from cpl_translation import TranslationSettings, TranslationServiceABC
|
from cpl_translation import TranslationSettings, TranslationServiceABC
|
||||||
|
|
||||||
|
from bot_core.configuration.bot_settings import BotSettings
|
||||||
|
|
||||||
|
|
||||||
class TestApplication(DiscordBotApplicationABC):
|
class TestApplication(DiscordBotApplicationABC):
|
||||||
|
|
||||||
@ -16,6 +19,28 @@ class TestApplication(DiscordBotApplicationABC):
|
|||||||
self._bot: DiscordBotServiceABC = services.get_service(DiscordBotServiceABC)
|
self._bot: DiscordBotServiceABC = services.get_service(DiscordBotServiceABC)
|
||||||
self._translation: TranslationServiceABC = services.get_service(TranslationServiceABC)
|
self._translation: TranslationServiceABC = services.get_service(TranslationServiceABC)
|
||||||
|
|
||||||
|
discord_bot_settings: DiscordBotSettings = config.get_configuration(DiscordBotSettings)
|
||||||
|
self._discord_settings = self._get_settings(discord_bot_settings)
|
||||||
|
|
||||||
|
def _get_settings(self, settings_from_config: DiscordBotSettings) -> DiscordBotSettings:
|
||||||
|
new_settings = DiscordBotSettings()
|
||||||
|
token = None if settings_from_config is None else settings_from_config.token
|
||||||
|
prefix = None if settings_from_config is None else settings_from_config.prefix
|
||||||
|
env_token = self._config.get_configuration('TOKEN')
|
||||||
|
env_prefix = self._config.get_configuration('PREFIX')
|
||||||
|
|
||||||
|
new_settings.from_dict({
|
||||||
|
'Token': env_token if token is None or token == '' else token,
|
||||||
|
'Prefix': ('! ' if self._is_string_invalid(env_prefix) else env_prefix) if self._is_string_invalid(prefix) else prefix
|
||||||
|
})
|
||||||
|
if new_settings.token is None or new_settings.token == '':
|
||||||
|
raise Exception('You have to configure discord token by appsettings or environment variables')
|
||||||
|
return new_settings
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _is_string_invalid(x):
|
||||||
|
return x is None or x == ''
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def config(self) -> ConfigurationABC:
|
def config(self) -> ConfigurationABC:
|
||||||
return self._config
|
return self._config
|
||||||
@ -28,6 +53,11 @@ class TestApplication(DiscordBotApplicationABC):
|
|||||||
self._translation.load_by_settings(self._configuration.get_configuration(TranslationSettings))
|
self._translation.load_by_settings(self._configuration.get_configuration(TranslationSettings))
|
||||||
|
|
||||||
async def main(self):
|
async def main(self):
|
||||||
|
if self._config.get_configuration('IS_UNITTEST'):
|
||||||
|
await self._bot.login(self._discord_settings.token)
|
||||||
|
self._bot.loop.create_task(self._bot.connect())
|
||||||
|
return
|
||||||
|
|
||||||
await self._bot.start_async()
|
await self._bot.start_async()
|
||||||
|
|
||||||
async def stop_async(self):
|
async def stop_async(self):
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
from cpl_core.configuration import ConfigurationABC
|
||||||
from cpl_core.console import Console, ForegroundColorEnum
|
from cpl_core.console import Console, ForegroundColorEnum
|
||||||
from cpl_core.dependency_injection import ServiceProviderABC
|
from cpl_core.dependency_injection import ServiceProviderABC
|
||||||
from cpl_core.logging import LoggerABC
|
from cpl_core.logging import LoggerABC
|
||||||
@ -15,7 +16,7 @@ class TestOnReadyEvent(OnReadyABC):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
logger: LoggerABC,
|
config: ConfigurationABC,
|
||||||
bot: DiscordBotServiceABC,
|
bot: DiscordBotServiceABC,
|
||||||
services: ServiceProviderABC,
|
services: ServiceProviderABC,
|
||||||
client_utils: ClientUtilsServiceABC,
|
client_utils: ClientUtilsServiceABC,
|
||||||
@ -23,13 +24,16 @@ class TestOnReadyEvent(OnReadyABC):
|
|||||||
):
|
):
|
||||||
OnReadyABC.__init__(self)
|
OnReadyABC.__init__(self)
|
||||||
|
|
||||||
self._logger = logger
|
self._config = config
|
||||||
self._bot = bot
|
self._bot = bot
|
||||||
self._services = services
|
self._services = services
|
||||||
self._client_utils = client_utils
|
self._client_utils = client_utils
|
||||||
self._t = t
|
self._t = t
|
||||||
|
|
||||||
async def on_ready(self):
|
async def on_ready(self):
|
||||||
|
if self._config.get_configuration('IS_UNITTEST'):
|
||||||
|
return
|
||||||
|
|
||||||
Console.write_line('\nStarting tests:\n')
|
Console.write_line('\nStarting tests:\n')
|
||||||
loader = unittest.TestLoader()
|
loader = unittest.TestLoader()
|
||||||
path = f'{os.path.dirname(os.path.realpath(__file__))}/../'
|
path = f'{os.path.dirname(os.path.realpath(__file__))}/../'
|
||||||
|
@ -20,7 +20,6 @@ class CommandTestCaseWithApp(TestCaseWithApp):
|
|||||||
_bot: Optional[DiscordBotServiceABC] = None
|
_bot: Optional[DiscordBotServiceABC] = None
|
||||||
_t: Optional[TranslatePipe] = None
|
_t: Optional[TranslatePipe] = None
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
TestCaseWithApp.setUpClass()
|
TestCaseWithApp.setUpClass()
|
||||||
@ -45,4 +44,5 @@ class CommandTestCaseWithApp(TestCaseWithApp):
|
|||||||
))
|
))
|
||||||
).click()
|
).click()
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
UI.driver.find_element(By.XPATH, '/html/body/div[1]/div[2]/div/div[1]/div/div[2]/div/div[1]/div/div/div[3]/div/main/form/div/div[2]/div/div[2]/div/div').send_keys(Keys.ENTER)
|
UI.driver.find_element(By.XPATH, '/html/body/div[1]/div[2]/div/div[1]/div/div[2]/div/div[1]/div/div/div[3]/div/main/form/div/div[2]/div/div[2]/div/div').send_keys(
|
||||||
|
Keys.ENTER)
|
||||||
|
@ -7,6 +7,6 @@ from ui_tests_shared.configuration.test_settings import TestSettings
|
|||||||
|
|
||||||
|
|
||||||
class Declarations:
|
class Declarations:
|
||||||
app: Optional[TestApplication]
|
app: Optional[TestApplication] = None
|
||||||
env: Optional[ApplicationEnvironmentABC]
|
env: Optional[ApplicationEnvironmentABC] = None
|
||||||
test_settings: Optional[TestSettings]
|
test_settings: Optional[TestSettings] = None
|
||||||
|
@ -1,9 +1,15 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
|
|
||||||
def async_test(coro):
|
class Async:
|
||||||
|
_loop = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def test(cls, coro):
|
||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
loop = asyncio.get_running_loop()
|
if cls._loop is None:
|
||||||
return loop.run_until_complete(coro(*args, **kwargs))
|
cls._loop = asyncio.get_event_loop()
|
||||||
|
|
||||||
|
return cls._loop.run_until_complete(coro(*args, **kwargs))
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import asyncio
|
||||||
|
import time
|
||||||
import unittest
|
import unittest
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
@ -18,10 +20,20 @@ class TestCaseWithApp(unittest.TestCase):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
if Declarations.app is None:
|
if Declarations.app is None:
|
||||||
get_app()
|
app = get_app()
|
||||||
|
import nest_asyncio
|
||||||
|
|
||||||
|
nest_asyncio.apply()
|
||||||
|
asyncio.run(app.run_async())
|
||||||
|
|
||||||
cls._config = Declarations.app.config
|
cls._config = Declarations.app.config
|
||||||
cls._services = Declarations.app.services
|
cls._services = Declarations.app.services
|
||||||
cls._test_settings: TestSettings = cls._config.get_configuration(TestSettings)
|
cls._test_settings: TestSettings = cls._config.get_configuration(TestSettings)
|
||||||
UI.set_settings(cls._test_settings)
|
UI.set_settings(cls._test_settings)
|
||||||
UI.login(cls._config.get_configuration('DISCORD_MAIL'), cls._config.get_configuration('DISCORD_PASSWORD'))
|
UI.login(cls._config.get_configuration('DISCORD_MAIL'), cls._config.get_configuration('DISCORD_PASSWORD'))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
if cls._config.get_configuration('IS_UNITTEST'):
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
loop.run_until_complete(Declarations.app.stop_async())
|
||||||
|
@ -54,3 +54,4 @@ class UI:
|
|||||||
|
|
||||||
WebDriverWait(cls.driver, 20).until(expected_conditions.url_matches(cls._test_settings.me_page_url))
|
WebDriverWait(cls.driver, 20).until(expected_conditions.url_matches(cls._test_settings.me_page_url))
|
||||||
time.sleep(4)
|
time.sleep(4)
|
||||||
|
cls._is_logged_in = True
|
||||||
|
19
kdb-bot/test/ui_tests_tests/cases/help_test_case.py
Normal file
19
kdb-bot/test/ui_tests_tests/cases/help_test_case.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import discord
|
||||||
|
|
||||||
|
from ui_tests_shared.command_test_case_with_app import CommandTestCaseWithApp
|
||||||
|
from ui_tests_shared.decorators import Async
|
||||||
|
|
||||||
|
|
||||||
|
class HelpTestCase(CommandTestCaseWithApp):
|
||||||
|
|
||||||
|
@Async.test
|
||||||
|
async def test_help(self):
|
||||||
|
correct_response = 'https://git.sh-edraft.de/sh-edraft.de/kd_discord_bot/wiki/Befehle'
|
||||||
|
self.send_command('help')
|
||||||
|
|
||||||
|
def check(m: discord.Message):
|
||||||
|
return m.content == correct_response and m.author.id == 998159802393964594
|
||||||
|
|
||||||
|
response = await self._bot.wait_for('message', check=check)
|
||||||
|
self.assertEqual(response.content, correct_response)
|
||||||
|
await self._bot.close()
|
@ -1,14 +1,12 @@
|
|||||||
import unittest
|
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
|
|
||||||
from ui_tests_shared.command_test_case_with_app import CommandTestCaseWithApp
|
from ui_tests_shared.command_test_case_with_app import CommandTestCaseWithApp
|
||||||
from ui_tests_shared.decorators import async_test
|
from ui_tests_shared.decorators import Async
|
||||||
|
|
||||||
|
|
||||||
class PingTestCase(CommandTestCaseWithApp):
|
class PingTestCase(CommandTestCaseWithApp):
|
||||||
|
|
||||||
@async_test
|
@Async.test
|
||||||
async def test_ping(self):
|
async def test_ping(self):
|
||||||
correct_response = self._t.transform('modules.base.pong')
|
correct_response = self._t.transform('modules.base.pong')
|
||||||
self.assertIsNotNone(correct_response)
|
self.assertIsNotNone(correct_response)
|
||||||
|
Loading…
Reference in New Issue
Block a user