diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 37324581..39bbf2d3 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -1,8 +1,7 @@ -name: Run UnitTests +name: Run CodeCov on: push: branches: - - master - dev workflow_dispatch: @@ -22,6 +21,11 @@ jobs: sudo apt-get update sudo apt install python3-dev python -m pip install build wheel + - name: Install test dependencies + run: | + sudo apt install libssl-dev libfann-dev portaudio19-dev libpulse-dev + pip install ovos-core[all] + pip install pytest pytest-timeout pytest-cov adapt-parser~=0.5 - name: Install repo run: | pip install . diff --git a/test/unittests/skills/test_mycroft_skill.py b/test/unittests/skills/test_mycroft_skill.py index ba49bb9f..071beff2 100644 --- a/test/unittests/skills/test_mycroft_skill.py +++ b/test/unittests/skills/test_mycroft_skill.py @@ -16,15 +16,16 @@ import sys import unittest -import pytest - from datetime import datetime from os.path import join, dirname, abspath from unittest.mock import MagicMock, patch +import pytest from adapt.intent import IntentBuilder -from ovos_config.config import Configuration from ovos_bus_client import Message +from ovos_config.config import Configuration + +from ovos_workshop.decorators import intent_handler, resting_screen_handler, intent_file_handler from ovos_workshop.skills.mycroft_skill import MycroftSkill from .mocks import base_config @@ -59,6 +60,21 @@ def vocab_base_path(): return join(dirname(__file__), '..', 'vocab_test') +class TestFunction(unittest.TestCase): + def test_resting_screen_handler(self): + class T(MycroftSkill): + def __init__(self): + self.name = 'TestObject' + + @resting_screen_handler('humbug') + def f(self): + pass + + test_class = T() + self.assertTrue('resting_handler' in dir(test_class.f)) + self.assertEqual(test_class.f.resting_handler, 'humbug') + + class TestMycroftSkill(unittest.TestCase): emitter = MockEmitter() regex_path = abspath(join(dirname(__file__), '../regex_test')) @@ -212,13 +228,15 @@ def _test_intent_file(self, s): 'file_name': join(dirname(__file__), 'intent_file', 'vocab', 'en-us', 'test.intent'), 'lang': 'en-us', - 'name': str(s.skill_id) + ':test.intent' + 'name': str(s.skill_id) + ':test.intent', + 'samples': [] }, { 'file_name': join(dirname(__file__), 'intent_file', 'vocab', 'en-us', 'test_ent.entity'), 'lang': 'en-us', - 'name': str(s.skill_id) + ':test_ent_87af9db6c8402bcfaa8ebc719ae4427c' + 'name': str(s.skill_id) + ':test_ent_87af9db6c8402bcfaa8ebc719ae4427c', + 'samples': [] } ] self.check_register_object_file(expected_types, expected_results) @@ -234,7 +252,7 @@ def test_register_decorators(self): """ Test decorated intents """ path_orig = sys.path sys.path.append(abspath(dirname(__file__))) - SimpleSkill5 = __import__('decorator_test_skill').TestSkill + s = SimpleSkill5() s.res_dir = abspath(join(dirname(__file__), 'intent_file')) s._startup(self.emitter, "A") @@ -247,6 +265,7 @@ def test_register_decorators(self): 'file_name': join(dirname(__file__), 'intent_file', 'vocab', 'en-us', 'test.intent'), 'lang': 'en-us', + 'samples': [], 'name': str(s.skill_id) + ':test.intent'}] self.check_register_decorators(expected) @@ -437,14 +456,14 @@ def test_voc_match_exact(self): exact=True)) self.assertFalse(s.voc_match("would you please turn off the lights", "turn_off_test", exact=True)) - + def test_voc_list(self): s = SimpleSkill1() s.root_dir = abspath(dirname(__file__)) self.assertEqual(s._voc_list("turn_off_test"), ["turn off", "switch off"]) - cache_key = s.lang+"turn_off_test" + cache_key = s.lang + "turn_off_test" self.assertIn(cache_key, s._voc_cache) def test_translate_locations(self): @@ -511,6 +530,23 @@ def test_native_langs(self): s.config_core['secondary_langs'] = secondary +class TestIntentCollisions(unittest.TestCase): + def test_two_intents_with_same_name(self): + emitter = MockEmitter() + skill = SameIntentNameSkill() + skill.bind(emitter) + with self.assertRaises(ValueError): + skill.initialize() + + def test_two_anonymous_intent_decorators(self): + """Two anonymous intent handlers should be ok.""" + emitter = MockEmitter() + skill = SameAnonymousIntentDecoratorsSkill() + skill.bind(emitter) + skill._register_decorated() + self.assertEqual(len(skill.intent_service.registered_intents), 2) + + class _TestSkill(MycroftSkill): def __init__(self): super().__init__() @@ -579,6 +615,21 @@ def stop(self): pass +class SimpleSkill5(MycroftSkill): + """ Test skill for intent_handler decorator. """ + + @intent_handler(IntentBuilder('a').require('Keyword').build()) + def handler(self, message): + pass + + @intent_file_handler('test.intent') + def handler2(self, message): + pass + + def stop(self): + pass + + class SimpleSkill6(_TestSkill): """ Test skill for padatious intent """ skill_id = 'A' @@ -603,3 +654,13 @@ def initialize(self): def handler(self, message): pass + + +class SameAnonymousIntentDecoratorsSkill(_TestSkill): + """Test skill for duplicate anonymous intent handlers.""" + skill_id = 'A' + + @intent_handler(IntentBuilder('').require('Keyword')) + @intent_handler(IntentBuilder('').require('OtherKeyword')) + def handler(self, message): + pass