Skip to content
This repository has been archived by the owner on Sep 8, 2024. It is now read-only.

Commit

Permalink
Add Voight Kampff support setting configurations
Browse files Browse the repository at this point in the history
Adds the "Given the user's {config} is {value}" step implementation

This will patch the configuration with a section from a dictionary that
can either be a global (shipped in
mycroft/res/{lang}/configurations.json) or shipped with the test
definition. The file should be named the same as the feature file but
instead of ".feature" the extension should be ".config.json".

mycroft/res/text/en-us/configurations.json contains a couple of
pre-defined configurations that can be applied
- units (metric/imperial)
- location (Stockholm)

After each scenario any applied patch will be cleared
  • Loading branch information
forslund committed May 7, 2020
1 parent a4c402e commit dd67519
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 0 deletions.
33 changes: 33 additions & 0 deletions mycroft/res/text/en-us/configurations.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"unit system": {
"metric": {"system_unit": "metric"},
"imperial": {"system_unit": "imperial"}
},
"location": {
"stockholm": {
"location": {
"city": {
"name": "Sockholm",
"state": {
"code": "SE.18",
"country": {
"code": "SE",
"name": "Sweden"
},
"name": "Stockholm"
}
},
"coordinate": {
"latitude": 59.38306,
"longitude": 16.66667
},
"timezone": {
"code": "Europe/Stockholm",
"dst_offset": 7200000,
"name": "Europe/Stockholm",
"offset": 3600000
}
}
}
}
}
21 changes: 21 additions & 0 deletions test/integrationtests/voight_kampff/features/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

from msm import MycroftSkillsManager
from mycroft.audio import wait_while_speaking
from mycroft.configuration import Configuration
from mycroft.messagebus.client import MessageBusClient
from mycroft.messagebus import Message
from mycroft.util import create_daemon
Expand Down Expand Up @@ -92,6 +93,9 @@ def before_all(context):
context.bus = bus
context.matched_message = None
context.log = log
context.original_config = {}
context.config = Configuration.get()
Configuration.set_config_update_handlers(bus)


def before_feature(context, feature):
Expand All @@ -110,9 +114,26 @@ def after_feature(context, feature):
sleep(1)


def reset_config(context):
"""Reset configuration with changes stored in original_config of context.
"""
context.log.info('Resetting patched configuration...')

context.bus.emit(Message('configuration.patch.clear'))
key = list(context.original_config)[0]
while context.config[key] != context.original_config[key]:
sleep(0.5)
context.original_config = {}


def after_scenario(context, scenario):
"""Wait for mycroft completion and reset any changed state."""
# TODO wait for skill handler complete
sleep(0.5)
wait_while_speaking()
context.bus.clear_messages()
context.matched_message = None

if context.original_config:
# something has changed, reset changes by done in the context
reset_config(context)
103 changes: 103 additions & 0 deletions test/integrationtests/voight_kampff/features/steps/configuration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Copyright 2020 Mycroft AI Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import json
from os.path import join, exists
import time

from behave import given
from mycroft.messagebus import Message
from mycroft.util import resolve_resource_file


def patch_config(context, patch):
"""Apply patch to config and wait for it to take effect.
Arguments:
context: Behave context for test
patch: patch to apply
"""
# store originals in context
for key in patch:
# If this patch is redefining an already changed key don't update
if key not in context.original_config:
context.original_config[key] = context.config.get(key)

# Patch config
patch_config_msg = Message('configuration.patch', {'config': patch})
context.bus.emit(patch_config_msg)

# Wait until one of the keys has been updated
key = list(patch.keys())[0]
while context.config.get(key) != patch[key]:
time.sleep(0.5)


def get_config_file_definition(configs_path, config, value):
"""Read config definition file and return the matching patch dict.
Arguments:
configs_path: path to the configuration patch json file
config: config value to fetch from the file
value: predefined value to fetch
Returns:
Patch dictionary or None.
"""
with open(configs_path) as f:
configs = json.load(f)
return configs.get(config, {}).get(value)


def get_global_config_definition(context, config, value):
"""Get config definitions included with Mycroft.
Arguments:
context: behave test context
config: config value to fetch from the file
value: predefined value to fetch
Returns:
Patch dictionary or None.
"""
configs_path = resolve_resource_file(join('text', context.lang,
'configurations.json'))
return get_config_file_definition(configs_path, config, value)


def get_feature_config_definition(context, config, value):
"""Get config feature specific config defintion
Arguments:
context: behave test context
config: config value to fetch from the file
value: predefined value to fetch
Returns:
Patch dictionary or None.
"""
feature_config = context.feature.filename.replace('.feature',
'.config.json')
if exists(feature_config):
return get_config_file_definition(feature_config, config, value)
else:
return None


@given('the user\'s {config} is {value}')
def given_config(context, config, value):
"""Patch the configuration with a specific config."""
patch_dict = (get_feature_config_definition(context, config, value) or
get_global_config_definition(context, config, value))
patch_config(context, patch_dict)
8 changes: 8 additions & 0 deletions test/integrationtests/voight_kampff/test_setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@
FEATURE_DIR = join(dirname(__file__), 'features') + '/'


def copy_config_definition_files(source, destination):
"""Copy all feature files from source to destination."""
# Copy feature files to the feature directory
for f in glob(join(source, '*.config.json')):
shutil.copyfile(f, join(destination, basename(f)))


def copy_feature_files(source, destination):
"""Copy all feature files from source to destination."""
# Copy feature files to the feature directory
Expand Down Expand Up @@ -141,6 +148,7 @@ def collect_test_cases(msm, skills):
behave_dir = join(skill.path, 'test', 'behave')
if exists(behave_dir):
copy_feature_files(behave_dir, FEATURE_DIR)
copy_config_definition_files(behave_dir, FEATURE_DIR)

step_dir = join(behave_dir, 'steps')
if exists(step_dir):
Expand Down

0 comments on commit dd67519

Please sign in to comment.