def setup(self): # Make blank experiment self.exp = experiment.Experiment() # Make blank routine self.routine = Routine(name="testRoutine", exp=self.exp) self.exp.addRoutine("testRoutine", self.routine) self.exp.flow.addRoutine(self.routine, 0) # Add loop around routine self.loop = TrialHandler(exp=self.exp, name="testLoop") self.exp.flow.addLoop(self.loop, 0, -1) # Make Mouse component self.comp = CodeComponent(exp=self.exp, parentName="testRoutine", name="testCode") self.routine.addComponent(self.comp)
def setup(self): # Make blank experiment self.exp = Experiment() # Make blank routine self.routine = Routine(name="testRoutine", exp=self.exp) self.exp.addRoutine("testRoutine", self.routine) self.exp.flow.addRoutine(self.routine, 0) # Add loop around routine self.loop = TrialHandler(exp=self.exp, name="testLoop") self.exp.flow.addLoop(self.loop, 0, -1) # Make a rect for when we need something to click on self.comp = PolygonComponent(exp=self.exp, parentName="testRoutine", name="testPolygon") self.routine.addComponent(self.comp)
class TestMouseComponent: """ Test that Mouse coponents have the correct params and write as expected. """ def setup(self): # Make blank experiment self.exp = Experiment() # Make blank routine self.routine = Routine(name="testRoutine", exp=self.exp) self.exp.addRoutine("testRoutine", self.routine) self.exp.flow.addRoutine(self.routine, 0) # Add loop around routine self.loop = TrialHandler(exp=self.exp, name="testLoop") self.exp.flow.addLoop(self.loop, 0, -1) # Make Mouse component self.comp = MouseComponent(exp=self.exp, parentName="testRoutine", name="testMouse") self.routine.addComponent(self.comp) # Make a rect for when we need something to click on self.target = PolygonComponent(exp=self.exp, parentName="testRoutine", name="testPolygon") self.routine.addComponent(self.target) def test_click_save_end_clickable_cases(self): """ Test all combinations of options for what to save, what can be clicked on & what kind of clicks to end the routine on. """ saveMouseStateCases = [ { 'val': "final", 'want': ["thisExp.addData('testMouse.x', x)" ], # should contain code for adding final value of x 'avoid': ["testMouse.x.append(x)"] }, # should not contain code to update testMouse.x in frame loop { 'val': "on click", 'want': [ "thisExp.addData('testMouse.x', testMouse.x)", # should add testMouse.x at the end "testMouse.x.append(x)" ], # should contain code to update testMouse.x in frame loop 'avoid': ["thisExp.addData('testMouse.x', x)"] }, # should not add final value of x { 'val': "on valid click", 'want': [ "thisExp.addData('testMouse.x', testMouse.x)", # should add testMouse.x at the end "testMouse.x.append(x)", # should contain code to update testMouse.x in frame loop "if gotValidClick:" ], # should check for valid clicks 'avoid': ["thisExp.addData('testMouse.x', x)"] }, # should not add final value of x { 'val': "every frame", 'want': [ "thisExp.addData('testMouse.x', testMouse.x)", # should add testMouse.x at the end "testMouse.x.append(x)" ], # should contain code to update testMouse.x in frame loop 'avoid': ["thisExp.addData('testMouse.x', x)"] }, # should not add final value of x { 'val': "never", 'want': [], 'avoid': [ "thisExp.addData('testMouse.x', testMouse.x)", # should not add testMouse.x at the end "testMouse.x.append(x)", # should not contain code to update testMouse.x in frame loop "thisExp.addData('testMouse.x', x)" ] }, # should not add final value of x]}, ] forceEndRoutineOnPressCases = [ { 'val': "never", 'want': [], 'avoid': [ "# abort routine on response", # should not include code to abort routine "# abort routine on response" ] }, { 'val': "any click", 'want': ["# abort routine on response" ], # should include code to abort routine on response 'avoid': [] }, { 'val': "valid click", 'want': [ "# abort routine on response", # should include code to abort routine on response "if gotValidClick:" ], # should check for valid clicks 'avoid': [] }, ] clickableCases = [ { 'val': "[]", 'want': [], 'avoid': ["clickableList = [testPolygon]"] }, # should not define a populated clickables list { 'val': "[testPolygon]", 'want': [], 'avoid': ["clickableList = []"] }, # should not define a blank clickables list ] # Iterate through saveMouseState cases for SMScase in saveMouseStateCases: # Set saveMouseState self.comp.params['saveMouseState'].val = SMScase['val'] for FEROPcase in forceEndRoutineOnPressCases: # Set forceEndRoutineOnPress self.comp.params['forceEndRoutineOnPress'].val = FEROPcase[ 'val'] for Ccase in clickableCases: # Set clickable self.comp.params['clickable'].val = Ccase['val'] # Compile script script = self.exp.writeScript(target="PsychoPy") try: # Look for wanted phrases for phrase in SMScase['want']: assert phrase in script, ( f"{phrase} not found in script when saveMouseState={self.comp.params['saveMouseState']}, " f"forceEndRoutineOnPress={self.comp.params['forceEndRoutineOnPress']} and " f"clickable={self.comp.params['clickable']}") for phrase in FEROPcase['want']: assert phrase in script, ( f"{phrase} not found in script when saveMouseState={self.comp.params['saveMouseState']}, " f"forceEndRoutineOnPress={self.comp.params['forceEndRoutineOnPress']} and " f"clickable={self.comp.params['clickable']}") for phrase in Ccase['want']: assert phrase in script, ( f"{phrase} not found in script when saveMouseState={self.comp.params['saveMouseState']}, " f"forceEndRoutineOnPress={self.comp.params['forceEndRoutineOnPress']} and " f"clickable={self.comp.params['clickable']}") # Check there's no avoid phrases for phrase in SMScase['avoid']: assert phrase not in script, ( f"{phrase} found in script when saveMouseState={self.comp.params['saveMouseState']}, " f"forceEndRoutineOnPress={self.comp.params['forceEndRoutineOnPress']} and " f"clickable={self.comp.params['clickable']}") for phrase in FEROPcase['avoid']: assert phrase not in script, ( f"{phrase} found in script when saveMouseState={self.comp.params['saveMouseState']}, " f"forceEndRoutineOnPress={self.comp.params['forceEndRoutineOnPress']} and " f"clickable={self.comp.params['clickable']}") for phrase in Ccase['avoid']: assert phrase not in script, ( f"{phrase} found in script when saveMouseState={self.comp.params['saveMouseState']}, " f"forceEndRoutineOnPress={self.comp.params['forceEndRoutineOnPress']} and " f"clickable={self.comp.params['clickable']}") except AssertionError as err: # If any assertion fails, save script to view filename = Path( TESTS_DATA_PATH ) / f"{__class__.__name__}_clicks_cases_local.py" with open(filename, "w") as f: f.write(script) # Append ref to saved script in error message print(f"Script saved at: {filename}") # Raise original error raise err
def test_muting(self): """ Test that component and standalone routines are muted under the correct conditions (i.e. if target is unimplemented or if disabled) """ # Make experiment to hold everything exp = Experiment() comp_rt = Routine("comp_rt", exp) comp_rt = exp.addRoutine("comp_rt", comp_rt) exp.flow.append(comp_rt) # Define some routines/components which should or should not compile exemplars = [] # standalone routine + disabled + no target obj = UnknownRoutine(exp, name="test_rt_disabled_notarget") obj.disabled = True obj.targets = [] exp.addStandaloneRoutine(obj.name, obj) exp.flow.append(obj) exemplars.append({"obj": obj, "ans": []}) # standalone routine + disabled + py target obj = UnknownRoutine(exp, name="test_rt_disabled_pytarget") obj.disabled = True obj.targets = ['PsychoPy'] exp.addStandaloneRoutine(obj.name, obj) exp.flow.append(obj) exemplars.append({"obj": obj, "ans": []}) # standalone routine + disabled + js target obj = UnknownRoutine(exp, name="test_rt_disabled_jstarget") obj.disabled = True obj.targets = ['PsychoJS'] exp.addStandaloneRoutine(obj.name, obj) exp.flow.append(obj) exemplars.append({"obj": obj, "ans": []}) # standalone routine + disabled + both targets obj = UnknownRoutine(exp, name="test_rt_disabled_bothtarget") obj.disabled = True obj.targets = ['PsychoPy', 'PsychoJS'] exp.addStandaloneRoutine(obj.name, obj) exp.flow.append(obj) exemplars.append({"obj": obj, "ans": []}) # standalone routine + enabled + no target obj = UnknownRoutine(exp, name="test_rt_enabled_notarget") obj.disabled = False obj.targets = [] exp.addStandaloneRoutine(obj.name, obj) exp.flow.append(obj) exemplars.append({"obj": obj, "ans": obj.targets}) # standalone routine + enabled + py target obj = UnknownRoutine(exp, name="test_rt_enabled_pytarget") obj.disabled = False obj.targets = ['PsychoPy'] exp.addStandaloneRoutine(obj.name, obj) exp.flow.append(obj) exemplars.append({"obj": obj, "ans": obj.targets}) # standalone routine + enabled + js target obj = UnknownRoutine(exp, name="test_rt_enabled_jstarget") obj.disabled = False obj.targets = ['PsychoJS'] exp.addStandaloneRoutine(obj.name, obj) exp.flow.append(obj) exemplars.append({"obj": obj, "ans": obj.targets}) # standalone routine + enabled + both target obj = UnknownRoutine(exp, name="test_rt_enabled_bothtarget") obj.disabled = False obj.targets = ['PsychoPy', 'PsychoJS'] exp.addStandaloneRoutine(obj.name, obj) exp.flow.append(obj) exemplars.append({"obj": obj, "ans": obj.targets}) # component + disabled + no target obj = UnknownComponent(exp, parentName="comp_rt", name="test_cmp_disabled_notarget") obj.disabled = True obj.targets = [] comp_rt.addComponent(obj) exemplars.append({"obj": obj, "ans": []}) # component + disabled + py target obj = UnknownComponent(exp, parentName="comp_rt", name="test_cmp_disabled_pytarget") obj.disabled = True obj.targets = ['PsychoPy'] comp_rt.addComponent(obj) exemplars.append({"obj": obj, "ans": []}) # component + disabled + js target obj = UnknownComponent(exp, parentName="comp_rt", name="test_cmp_disabled_jstarget") obj.disabled = True obj.targets = ['PsychoJS'] comp_rt.addComponent(obj) exemplars.append({"obj": obj, "ans": []}) # component + disabled + both target obj = UnknownComponent(exp, parentName="comp_rt", name="test_cmp_disabled_bothtarget") obj.disabled = True obj.targets = ['PsychoPy', 'PsychoJS'] comp_rt.addComponent(obj) exemplars.append({"obj": obj, "ans": []}) # component + enabled + no target obj = UnknownComponent(exp, parentName="comp_rt", name="test_cmp_enabled_notarget") obj.disabled = False obj.targets = [] comp_rt.addComponent(obj) exemplars.append({"obj": obj, "ans": obj.targets}) # component + enabled + py target obj = UnknownComponent(exp, parentName="comp_rt", name="test_cmp_enabled_pytarget") obj.disabled = False obj.targets = ['PsychoPy'] comp_rt.addComponent(obj) exemplars.append({"obj": obj, "ans": obj.targets}) # component + enabled + js target obj = UnknownComponent(exp, parentName="comp_rt", name="test_cmp_enabled_jstarget") obj.disabled = False obj.targets = ['PsychoJS'] comp_rt.addComponent(obj) exemplars.append({"obj": obj, "ans": obj.targets}) # component + enabled + both target obj = UnknownComponent(exp, parentName="comp_rt", name="test_cmp_enabled_bothtarget") obj.disabled = False obj.targets = ['PsychoPy', 'PsychoJS'] comp_rt.addComponent(obj) exemplars.append({"obj": obj, "ans": obj.targets}) tykes = [] # Compile experiment pyScript = exp.writeScript(target="PsychoPy") # jsScript = exp.writeScript(target="PsychoJS") ## disabled until js can compile without saving # Test all cases for case in exemplars + tykes: # Check Python script if "PsychoPy" in case['ans']: assert case['obj'].name in pyScript, ( f"{case['obj']} not found in Python script when it should be." ) else: assert case['obj'].name not in pyScript, ( f"{case['obj']} found in Python script when it should not be." )
class TestPolygonComponent(_TestBaseComponentsMixin, _TestDisabledMixin): """ Test that Polygon coponents have the correct params and write as expected. """ def setup(self): # Make blank experiment self.exp = Experiment() # Make blank routine self.routine = Routine(name="testRoutine", exp=self.exp) self.exp.addRoutine("testRoutine", self.routine) self.exp.flow.addRoutine(self.routine, 0) # Add loop around routine self.loop = TrialHandler(exp=self.exp, name="testLoop") self.exp.flow.addLoop(self.loop, 0, -1) # Make a rect for when we need something to click on self.comp = PolygonComponent(exp=self.exp, parentName="testRoutine", name="testPolygon") self.routine.addComponent(self.comp) def test_vertices_usage(self): """ Test that vertices values are used only under the correct conditions """ # Define values to look for and avoid in code according to value of shape cases = [ # Shape is a line { 'val': "line", 'seek': ["visual.Line("], 'avoid': ["___nVertices___", "___vertices___"] }, { 'val': "triangle", 'seek': ["visual.ShapeStim("], 'avoid': ["___nVertices___", "___vertices___"] }, { 'val': "rectangle", 'seek': ["visual.Rect("], 'avoid': ["___nVertices___", "___vertices___"] }, { 'val': "circle", 'seek': ["visual.ShapeStim(", "vertices='circle'"], 'avoid': ["___nVertices___", "___vertices___"] }, { 'val': "cross", 'seek': ["visual.ShapeStim(", "vertices='cross'"], 'avoid': ["___nVertices___", "___vertices___"] }, { 'val': "star", 'seek': ["visual.ShapeStim(", "vertices='star7'"], 'avoid': ["___nVertices___", "___vertices___"] }, { 'val': "regular polygon...", 'seek': ["___nVertices___", "visual.Polygon("], 'avoid': ["___vertices___"] }, { 'val': "custom polygon...", 'seek': ["___vertices___", "visual.ShapeStim("], 'avoid': ["___nVertices___"] }, ] # Setup component with markers for nVertices and vertices self.comp.params['nVertices'].val = "___nVertices___" self.comp.params['vertices'].val = "___vertices___" # Test each case for case in cases: # Set shape self.comp.params['shape'].val = case['val'] # Write experiment pyScript = self.exp.writeScript(target="PsychoPy") # Look for sought values in experiment script for seekVal in case['seek']: assert seekVal in pyScript, ( f"Could not find wanted value `{seekVal}` in experiment when polygon shape was {case['val']}." ) # Look for avoid values in experiment script for avoidVal in case['avoid']: assert avoidVal not in pyScript, ( f"Found unwanted value `{avoidVal}` in experiment when polygon shape was {case['val']}." )
class TestCodeComponent(_TestBaseComponentsMixin, _TestDisabledMixin): """ Test that Code coponents have the correct params and write as expected. """ @classmethod def setup_class(cls): cls.exp = experiment.Experiment() # create once, not every test try: cls.tempDir = mkdtemp(dir=Path(__file__).root, prefix='psychopy-tests-app') except (PermissionError, OSError): # can't write to root on Linux cls.tempDir = mkdtemp(prefix='psychopy-tests-app') def setup(self): # Make blank experiment self.exp = experiment.Experiment() # Make blank routine self.routine = Routine(name="testRoutine", exp=self.exp) self.exp.addRoutine("testRoutine", self.routine) self.exp.flow.addRoutine(self.routine, 0) # Add loop around routine self.loop = TrialHandler(exp=self.exp, name="testLoop") self.exp.flow.addLoop(self.loop, 0, -1) # Make Mouse component self.comp = CodeComponent(exp=self.exp, parentName="testRoutine", name="testCode") self.routine.addComponent(self.comp) def test_all_code_component_tabs(self): # Names of each tab in a Code component tabs = { 'Before Experiment': '___before_experiment___', 'Begin Experiment': '___begin_experiment___', 'Begin Routine': '___begin_routine___', 'Each Frame': '___each_frame___', 'End Routine': '___end_routine___', 'End Experiment': '___end_experiment___', } # Add markers to component for paramName, marker in tabs.items(): jsParamName = paramName.replace(" ", " JS ") self.comp.params[paramName].val = self.comp.params[jsParamName].val = marker # Write script pyScript = self.exp.writeScript(target="PsychoPy") jsScript = self.exp.writeScript(target="PsychoJS") # Check that code from each tab exists in compiled script for lang, script in {"Python": pyScript, "JS": jsScript}.items(): for paramName, marker in tabs.items(): try: assert marker in script, ( f"Could not find {marker} in {lang} script." ) except AssertionError as err: # If test fails here, save the file for easy access ext = ".py" if lang == "Python" else ".js" with open(Path(TESTS_DATA_PATH) / ("test_all_code_component_tabs_local" + ext), "w") as f: f.write(script) raise err if lang == "Python": # Check py code is in the right order in Python (not applicable to JS as it's non-linear) assert script.find('___before_experiment___') < script.find('___begin_experiment___') < script.find( '___begin_routine___') < script.find('___each_frame___') < script.find('___end_routine___') < script.find( '___end_experiment___') assert script.find('___before_experiment___') < script.find('visual.Window') < script.find( '___begin_experiment___') < script.find('continueRoutine = True') assert script.find('continueRoutine = True') < script.find('___begin_routine___') < script.find( 'while continueRoutine:') < script.find('___each_frame___') assert script.find('thisComponent.setAutoDraw(False)') < script.find('___end_routine___') < script.find( 'routineTimer.reset()') < script.find('___end_experiment___')