Esempio n. 1
0
 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)
Esempio n. 2
0
 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)
Esempio n. 3
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
Esempio n. 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."
                )
Esempio n. 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']}."
                )
Esempio n. 6
0
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___')