def test_disabled_routine_is_not_written_to_script(self):
     # Make experiment and two test routines
     exp = Experiment()
     rt1 = UnknownRoutine(exp, name="testRoutine1")
     rt2 = UnknownRoutine(exp, name="testRoutine2")
     # Disable one routine
     rt1.params['disabled'].val = True
     rt2.params['disabled'].val = False
     # Add routines to expriment
     exp.addStandaloneRoutine("testRoutine1", rt1)
     exp.flow.addRoutine(rt1, 0)
     exp.addStandaloneRoutine("testRoutine2", rt2)
     exp.flow.addRoutine(rt2, 0)
     # Write python script
     pyScript = exp.writeScript(target="PsychoPy")
     # Check that one routine is present and the other is not
     assert "testRoutine1" not in pyScript and "testRoutine2" in pyScript
Exemple #2
0
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
Exemple #3
0
def test_get_resources_js():
    cases = [
        # Resource not handled, no loop present
        {'exp': "unhandled_noloop",
         'seek': ['blue.png'],
         'avoid': ['white.png', 'yellow.png', 'groups.csv', 'groupA.csv', 'groupB.csv']},
        # Resource not handled, loop defined by string
        {'exp': "unhandled_strloop",
         'seek': ['blue.png', 'white.png', 'groupA.csv'],
         'avoid': ['yellow.png', 'groupB.csv', 'groups.csv']},
        # Resource not handled, loop defined by constructed string
        {'exp': "unhandled_constrloop",
         'seek': ['blue.png', 'white.png', 'yellow.png', 'groupA.csv', 'groupB.csv', 'groups.csv'],
         'avoid': []},
        # Resource not handled, loop defined by constructed string from loop
        {'exp': "unhandled_recurloop",
         'seek': ['blue.png', 'white.png', 'yellow.png', 'groupA.csv', 'groupB.csv', 'groups.csv'],
         'avoid': []},

        # Resource handled by static component, no loop present
        {'exp': "handledbystatic_noloop",
         'seek': [],
         'avoid': ['blue.png', 'white.png', 'yellow.png', 'groups.csv', 'groupA.csv', 'groupB.csv']},
        # Resource handled by static component, loop defined by string
        {'exp': "handledbystatic_strloop",
         'seek': ['groupA.csv'],
         'avoid': ['blue.png', 'white.png', 'yellow.png', 'groupB.csv', 'groups.csv']},
        # Resource handled by static component, loop defined by constructed string
        {'exp': "handledbystatic_constrloop",
         'seek': ['groupA.csv', 'groupB.csv', 'groups.csv'],
         'avoid': ['blue.png', 'white.png', 'yellow.png']},
        # Resource handled by static component, loop defined by constructed string from loop
        {'exp': "handledbystatic_recurloop",
         'seek': ['groupA.csv', 'groupB.csv', 'groups.csv'],
         'avoid': ['blue.png', 'white.png', 'yellow.png']},

        # Resource handled by resource manager component, no loop present
        {'exp': "handledbyrm_noloop",
         'seek': [],
         'avoid': ['blue.png', 'white.png', 'yellow.png', 'groups.csv', 'groupA.csv', 'groupB.csv']},
        # Resource handled by resource manager component, loop defined by constructed string
        {'exp': "handledbyrm_strloop",
         'seek': ['groupA.csv'],
         'avoid': ['blue.png', 'white.png', 'yellow.png', 'groupB.csv', 'groups.csv']},
        # Resource handled by resource manager component, loop defined by constructed string
        {'exp': "handledbyrm_constrloop",
         'seek': ['groupA.csv', 'groupB.csv', 'groups.csv'],
         'avoid': ['blue.png', 'white.png', 'yellow.png']},
        # Resource handled by resource manager component, loop defined by constructed string from loop
        {'exp': "handledbyrm_recurloop",
         'seek': ['groupA.csv', 'groupB.csv', 'groups.csv'],
         'avoid': ['blue.png', 'white.png', 'yellow.png']},
    ]

    exp = Experiment()
    for case in cases:
        # Load experiment
        exp.loadFromXML(Path(TESTS_DATA_PATH) / "test_get_resources" / (case['exp'] + ".psyexp"))
        # Write to JS
        script = exp.writeScript(target="PsychoJS")
        # Extract resources def at start of experiment
        resources = re.search("(?<=resources: \[)[^\]]*", script).group(0)
        # Check that all "seek" phrases are included
        for phrase in case['seek']:
            assert phrase in resources, f"'{phrase}' was not found in resources for {case['exp']}.psyexp"
        # Check that all "avoid" phrases are excluded
        for phrase in case['avoid']:
            assert phrase not in resources, f"'{phrase}' was found in resources for {case['exp']}.psyexp"
Exemple #4
0
    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."
                )
Exemple #5
0
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']}."
                )