Skip to content

Commit 13d74be

Browse files
authored
Merge pull request #12 from DigitalPhonetics/unit_tests
Unit tests
2 parents a67478b + 5b01036 commit 13d74be

23 files changed

+5386
-7
lines changed

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ wheels/
3636
*.egg
3737
MANIFEST
3838
adviser_env/
39+
adviserenv/
3940

4041
# PyInstaller
4142
# Usually these files are written by a python script from a template
@@ -198,4 +199,7 @@ tools/opensmile-2.3.0/
198199

199200
adviser/tools/opencv*
200201
adviser/tools/OpenFace
201-
adviser/tools/cppzmq
202+
adviser/tools/cppzmq*
203+
adviser/tools/dlib*
204+
adviser/tools/zeromq*
205+
adviser/tools/*.zip

adviser/services/policy/policy_handcrafted.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def dialog_start(self):
7575
self.s_index = 0 # the index in current suggestions for the current system reccomendation
7676

7777
@PublishSubscribe(sub_topics=["beliefstate"], pub_topics=["sys_act", "sys_state"])
78-
def choose_sys_act(self, beliefstate: BeliefState = None) \
78+
def choose_sys_act(self, beliefstate: BeliefState) \
7979
-> dict(sys_act=SysAct):
8080

8181
"""
@@ -103,6 +103,10 @@ def choose_sys_act(self, beliefstate: BeliefState = None) \
103103
sys_state["last_act"] = sys_act
104104
return {'sys_act': sys_act, "sys_state": sys_state}
105105

106+
# Handles case where it was the first turn, but there are user acts
107+
elif self.first_turn:
108+
self.first_turn = False
109+
106110
if self.turns >= self.max_turns:
107111
sys_act = SysAct()
108112
sys_act.type = SysActionType.Bye
@@ -125,10 +129,18 @@ def choose_sys_act(self, beliefstate: BeliefState = None) \
125129
sys_act.type = SysActionType.RequestMore
126130
# If user only says hello, request a random slot to move dialog along
127131
elif UserActionType.Hello in beliefstate["user_acts"] or UserActionType.SelectDomain in beliefstate["user_acts"]:
128-
sys_act = SysAct()
129-
sys_act.type = SysActionType.Request
130-
slot = self._get_open_slot(beliefstate)
131-
sys_act.add_value(slot)
132+
# as long as there are open slots, choose one randomly
133+
if self._get_open_slot(beliefstate):
134+
sys_act = SysAct()
135+
sys_act.type = SysActionType.Request
136+
slot = self._get_open_slot(beliefstate)
137+
sys_act.add_value(slot)
138+
139+
# If there are no more open slots, ask the user if you can help with anything else since
140+
# this can only happen in the case an offer has already been made --LV
141+
else:
142+
sys_act = SysAct()
143+
sys_act.type = SysActionType.RequestMore
132144

133145
# If we switch to the domain, start a new dialog
134146
if UserActionType.SelectDomain in beliefstate["user_acts"]:

adviser/services/policy/rl/train_dqnpolicy.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ def train(domain_name: str, log_to_file: bool, seed: int, train_epochs: int, tra
117117

118118
if __name__ == "__main__":
119119
# possible test domains
120-
domains = ['courses', 'lecturers']
120+
domains = ['lecturers']
121121

122122
# command line arguments
123123
parser = argparse.ArgumentParser()

adviser/tests/bst/bst_test.py

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
import os
2+
import sys
3+
from copy import deepcopy
4+
5+
def get_root_dir():
6+
return os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
7+
8+
9+
sys.path.append(get_root_dir())
10+
from services.bst import HandcraftedBST
11+
from utils import UserActionType, UserAct
12+
13+
14+
def test_initialize_bst_without_domain():
15+
"""
16+
Tests whether the initialization of a BST without domain executes without errors.
17+
"""
18+
HandcraftedBST()
19+
20+
21+
def test_reset_beliefstate_on_start(bst):
22+
"""
23+
Tests whether the beliefstate resets on dialog start.
24+
25+
Args:
26+
bst: BST Object (given in conftest.py)
27+
"""
28+
previous_bs = bst.bs
29+
bst.dialog_start()
30+
assert previous_bs is not bst.bs
31+
32+
33+
def test_update_bst_without_user_act(bst):
34+
"""
35+
Tests whether the BST skips an update if no user act is given.
36+
37+
Args:
38+
bst: BST Object (given in conftest.py)
39+
"""
40+
previous_bs = deepcopy(bst.bs)
41+
bs_dict = bst.update_bst(None)
42+
assert type(bs_dict) == dict
43+
assert len(bs_dict) == 1
44+
assert 'beliefstate' in bs_dict
45+
assert bs_dict['beliefstate'] == bst.bs
46+
assert str(bs_dict['beliefstate']) == str(previous_bs)
47+
48+
49+
def test_update_bst_with_user_act(bst, constraintA):
50+
"""
51+
Tests whether the BST updates its beliefstate if a user act is given.
52+
53+
Args:
54+
bst: BST Object (given in conftest.py)
55+
constraintA (dict): an existing slot-value pair in the domain (given in
56+
conftest_<domain>.py)
57+
"""
58+
user_acts = [UserAct(act_type=UserActionType.Inform, slot=constraintA['slot'],
59+
value=constraintA['value'])]
60+
previous_bs = deepcopy(bst.bs)
61+
bs_dict = bst.update_bst(user_acts)
62+
assert type(bs_dict) == dict
63+
assert len(bs_dict) == 1
64+
assert 'beliefstate' in bs_dict
65+
assert bs_dict['beliefstate'] == bst.bs
66+
assert 'user_acts' in bs_dict['beliefstate']
67+
assert 'num_matches' in bs_dict['beliefstate']
68+
assert 'discriminable' in bs_dict['beliefstate']
69+
assert str(bs_dict['beliefstate']) != str(previous_bs)
70+
71+
72+
def test_update_bst_sets_number_of_db_matches(bst, constraintA):
73+
"""
74+
Tests whether updating the BST also updates the number of matches in the database and whether they are discriminable.
75+
76+
Args:
77+
bst: BST Object (given in conftest.py)
78+
constraintA (dict): an existing slot-value pair in the domain (given in
79+
conftest_<domain>.py)
80+
"""
81+
bst.bs['informs'][constraintA['slot']] = {constraintA['value']: 0.5}
82+
user_acts = [UserAct(act_type=UserActionType.Hello)]
83+
bs_dict = bst.update_bst(user_acts)
84+
assert 'num_matches' in bs_dict['beliefstate']
85+
assert type(bs_dict['beliefstate']['num_matches']) == int
86+
assert bs_dict['beliefstate']['num_matches'] > -1
87+
assert 'discriminable' in bs_dict['beliefstate']
88+
assert type(bs_dict['beliefstate']['discriminable']) == bool
89+
90+
91+
def test_reset_informs_removes_slots_from_informs(bst):
92+
"""
93+
Tests whether reset informs removes all given inform slots.
94+
95+
Args:
96+
bst: BST Object (given in conftest.py)
97+
"""
98+
acts = [UserAct(act_type=UserActionType.Inform, slot='foo', value='bar'),
99+
UserAct(act_type=UserActionType.Inform, slot='bar', value='foo')]
100+
bst.bs['informs'] = {'foo': {'bar': 0.5}, 'bar': {'foo': 0.3}, 'baz': {'foo': 0.6}}
101+
bst._reset_informs(acts)
102+
assert all(act.slot not in bst.bs['informs'] for act in acts)
103+
104+
105+
def test_reset_informs_resets_only_informs(bst):
106+
"""
107+
Tests whether reset informs removes only inform slots.
108+
109+
Args:
110+
bst: BST Object (given in conftest.py)
111+
"""
112+
acts = [UserAct(act_type=UserActionType.Inform, slot='foo', value='bar'),
113+
UserAct(act_type=UserActionType.Request, slot='bar', value='foo')]
114+
bst.bs['informs'] = {'foo': {'bar': 0.5}, 'bar': {'foo': 0.3}, 'baz': {'foo': 0.6}}
115+
bst._reset_informs(acts)
116+
assert all(act.slot not in bst.bs['informs'] for act in acts if act.type ==
117+
UserActionType.Inform)
118+
assert 'bar' in bst.bs['informs']
119+
120+
121+
def test_reset_requests(bst):
122+
"""
123+
Tests resetting the requests dict of the beliefstate.
124+
125+
Args:
126+
bst: BST Object (given in conftest.py)
127+
"""
128+
bst.bs['requests']['foo'] = 0.5
129+
bst._reset_requests()
130+
assert bst.bs['requests'] == {}
131+
132+
133+
def test_get_all_usr_action_types(bst):
134+
"""
135+
Tests whether requesting user action types will return all of them.
136+
137+
Args:
138+
bst: BST Object (given in conftest.py)
139+
"""
140+
user_action_types = [UserActionType.Inform, UserActionType.Request, UserActionType.Hello,
141+
UserActionType.Thanks]
142+
user_acts = [UserAct(act_type=act_type) for act_type in user_action_types]
143+
act_type_set = bst._get_all_usr_action_types(user_acts)
144+
assert act_type_set == set(user_action_types)
145+
146+
147+
def test_handle_user_acts_resets_informs_about_primary_key_for_inform_act(bst):
148+
"""
149+
Tests whether the informs about the primary key reset when handling a user inform.
150+
151+
Args:
152+
bst: BST Object (given in conftest.py)
153+
"""
154+
bst.bs['informs'][bst.domain.get_primary_key()] = {'foo': 0.5}
155+
bst.bs['user_acts'] = [UserActionType.Inform]
156+
bst._handle_user_acts([])
157+
assert bst.domain.get_primary_key() not in bst.bs['informs']
158+
159+
160+
def test_handle_user_acts_resets_informs_and_request_for_select_domain_act(bst):
161+
"""
162+
Tests whether the informs and requests reset when handling a new domain selection by the user.
163+
164+
Args:
165+
bst: BST Object (given in conftest.py)
166+
"""
167+
bst.bs['informs']['foo'] = {'bar': 0.5}
168+
bst.bs['requests']['foo'] = 0.5
169+
bst.bs['user_acts'] = [UserActionType.SelectDomain]
170+
bst._handle_user_acts([])
171+
assert bst.bs['informs'] == {}
172+
assert bst.bs['requests'] == {}
173+
174+
175+
def test_handle_user_acts_for_user_request(bst):
176+
"""
177+
Tests whether the requests are set correctly when handling a user request.
178+
179+
Args:
180+
bst: BST Object (given in conftest.py)
181+
"""
182+
slot = 'foo'
183+
score = 0.5
184+
user_acts = [UserAct(act_type=UserActionType.Request, slot=slot, score=score)]
185+
bst._handle_user_acts(user_acts)
186+
assert slot in bst.bs['requests']
187+
assert bst.bs['requests'][slot] == score
188+
189+
190+
def test_handle_user_acts_for_user_inform(bst):
191+
"""
192+
Tests whether the informs are set correctly when handling a user inform.
193+
194+
Args:
195+
bst: BST Object (given in conftest.py)
196+
"""
197+
slot = 'foo'
198+
value = 'bar'
199+
score = 0.5
200+
user_acts = [UserAct(act_type=UserActionType.Inform, slot=slot, value=value, score=score)]
201+
bst._handle_user_acts(user_acts)
202+
assert slot in bst.bs['informs']
203+
assert value in bst.bs['informs'][slot]
204+
assert bst.bs['informs'][slot][value] == score
205+
206+
207+
def test_handle_user_acts_for_user_negative_inform(bst):
208+
"""
209+
Tests whether handling a negative inform by the user deletes the corresponding inform value.
210+
211+
Args:
212+
bst: BST Object (given in conftest.py)
213+
"""
214+
slot = 'foo'
215+
value = 'bar'
216+
bst.bs['informs'][slot] = {value: 0.5}
217+
user_acts = [UserAct(act_type=UserActionType.NegativeInform, slot=slot, value=value)]
218+
bst._handle_user_acts(user_acts)
219+
assert value not in bst.bs['informs'][slot]
220+
221+
222+
def test_handle_user_acts_for_user_request_alternatives(bst, primkey_constraint):
223+
"""
224+
Tests whether the primary key is removed from the informs when handling a user request for
225+
alternatives.
226+
227+
Args:
228+
bst: BST Object (given in conftest.py)
229+
primkey_constraint (dict): slot-value pair for a primary key constraint (given in
230+
conftest_<domain>.py)
231+
"""
232+
bst.bs['informs'][primkey_constraint['slot']] = {primkey_constraint['value']: 0.5}
233+
user_acts = [UserAct(act_type=UserActionType.RequestAlternatives)]
234+
bst._handle_user_acts(user_acts)
235+
assert bst.domain.get_primary_key() not in bst.bs['informs']

adviser/tests/conftest.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import os
2+
import sys
3+
import argparse
4+
import pytest
5+
6+
def get_root_dir():
7+
return os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
8+
9+
sys.path.append(get_root_dir())
10+
from utils.beliefstate import BeliefState
11+
from utils.domain.jsonlookupdomain import JSONLookupDomain
12+
from services.policy import HandcraftedPolicy
13+
from services.bst import HandcraftedBST
14+
from services.simulator.goal import Goal
15+
from services.nlu.nlu import HandcraftedNLU
16+
from services.nlg import HandcraftedNLG
17+
from services.nlg.affective_nlg import HandcraftedEmotionNLG
18+
19+
from services.simulator.simulator import HandcraftedUserSimulator, Agenda
20+
21+
22+
pytest_plugins = ['conftest_superhero']
23+
24+
25+
@pytest.fixture
26+
def domain(domain_name):
27+
return JSONLookupDomain(domain_name)
28+
29+
@pytest.fixture
30+
def beliefstate(domain):
31+
bs = BeliefState(domain)
32+
return bs
33+
34+
@pytest.fixture
35+
def policy(domain):
36+
policy = HandcraftedPolicy(domain)
37+
policy.dialog_start()
38+
return policy
39+
40+
@pytest.fixture
41+
def bst(domain):
42+
return HandcraftedBST(domain)
43+
44+
@pytest.fixture
45+
def goal(domain):
46+
return Goal(domain)
47+
48+
@pytest.fixture
49+
def nlu(domain):
50+
nlu = HandcraftedNLU(domain)
51+
return nlu
52+
53+
@pytest.fixture
54+
def nlg(domain):
55+
nlg = HandcraftedNLG(domain)
56+
return nlg
57+
58+
@pytest.fixture
59+
def aff_nlg(domain):
60+
aff_nlg = HandcraftedEmotionNLG(domain)
61+
return aff_nlg
62+
63+
def agenda():
64+
return Agenda()
65+
66+
@pytest.fixture
67+
def simulator(domain):
68+
simulator = HandcraftedUserSimulator(domain)
69+
simulator.dialog_start()
70+
return simulator

0 commit comments

Comments
 (0)