示例#1
0
def array_element_tests(test, student_data, solution_data, feedback, *args, **kwargs):
    tests = []
    if not isinstance(student_data, list) or not isinstance(solution_data, list):
        # If student data is None; Feedback will be provided by a different test.
        return tests
    for i, (element_student_data, element_solution_data) in enumerate(
        zip(student_data, solution_data)
    ):
        if isinstance(feedback, str):
            item_feedback = Feedback(feedback)
        else:
            item_feedback = copy.deepcopy(feedback)
        item_feedback.message = item_feedback.message.format(
            ordinal=selectors.get_ord(i + 1),
            expected=element_solution_data,
            actual=element_student_data,
        )
        tests.append(
            test(
                element_student_data,
                element_solution_data,
                item_feedback,
                *args,
                **kwargs,
            )
        )
    return tests
def has_equal_conditional_formats(state, absolute=False, incorrect_msg=None):
    student_cond_formats = state.student_data["conditionalFormats"]
    solution_cond_formats = state.solution_data["conditionalFormats"]

    issues = []

    for i, (student_cond_format, solution_cond_format) in enumerate(
        zip(student_cond_formats, solution_cond_formats)
    ):
        ordinal = selectors.get_ord(i + 1)
        bound_rules = {
            key: RuleClass(student_cond_format, solution_cond_format, issues)
            for key, RuleClass in rule_types.items()
        }

        bound_rules["existence"](
            "booleanRule", f"The {ordinal} rule is incorrect, expected single color."
        )
        bound_rules["existence"](
            "gradientRule", f"The {ordinal} rule is incorrect, expected color scale."
        )
        if len(issues) == 0:
            bound_rules["equality"](
                "ranges", f"There ranges of the {ordinal} rule are incorrect."
            )

            bound_rules["equality"](
                "booleanRule.condition",
                f"There condition of the {ordinal} rule is incorrect.",
            )
            bound_rules["equality"](
                "booleanRule.format",
                f"There format of the {ordinal} rule is incorrect.",
            )

            bound_rules["equality"](
                "gradientRule.minpoint",
                f"There minpoint of the {ordinal} rule is incorrect.",
            )
            bound_rules["equality"](
                "gradientRule.midpoint",
                f"There minpoint of the {ordinal} rule is incorrect.",
            )
            bound_rules["equality"](
                "gradientRule.maxpoint",
                f"There maxpoint of the {ordinal} rule is incorrect.",
            )

    nb_issues = len(issues)
    if nb_issues > 0:
        _issues_msg = "\n".join([f"- {issue}" for issue in issues])
        _msg = (
            f"There {'are' if nb_issues > 1 else 'is'} {nb_issues} "
            f"issue{'s' if nb_issues > 1 else ''} with the conditional "
            f"formatting rules:\n\n{_issues_msg}\n"
        )
        state.do_test(_msg)
示例#3
0
def has_equal_single_series(state, number, min_range_str, series_type):
    base_path = f"basicChart.series.{number - 1}"
    min_range = Range(min_range_str)
    series_path = {
        "basicChart": {
            "source": f"{base_path}.series.sourceRange.sources",
            "color": f"{base_path}.color",
        }
    }
    series_equality = {"source": partial(equal_sources, min_range=min_range)}
    ordinal = selectors.get_ord(number)
    if state.node_name in series_path:
        state.do_test(
            EqualityTest(
                *state_selector(state)(series_path[state.node_name].get(series_type)),
                f"the {ordinal} series' {series_type} is not correct.",
                series_equality.get(series_type, lambda x, y: x == y),
            )
        )
    return state
示例#4
0
    def __call__(self, path, message, equal_func=lambda x, y: x == y):
        solution_array = safe_glom(self.solution_structure, path)
        student_array = safe_glom(self.student_structure, path)
        if not isinstance(student_array, list):
            return
        if not isinstance(solution_array, list):
            return
        if solution_array != student_array:
            matches = [equal_func(x, y) for x, y in zip(student_array, solution_array)]
            mismatch_reducer = lambda all, x: all if x[1] else [*all, x[0]]
            mismatch_indices = functools.reduce(
                mismatch_reducer, enumerate(matches), []
            )

            self.issues.extend(
                [
                    message.format(
                        ordinal=selectors.get_ord(i + 1),
                        expected=solution_array[i],
                        actual=student_array[i],
                    )
                    for i in mismatch_indices
                ]
            )
示例#5
0
def test_ord(num, ord):
    assert get_ord(num) == ord
def has_equal_conditional_formats(state, absolute=False, incorrect_msg=None):
    sct_range_filter = partial(conditional_format_filter, state.sct_range)
    student_cond_formats = list(
        filter(sct_range_filter, state.student_data["conditionalFormats"]))
    solution_cond_formats = list(
        filter(sct_range_filter, state.solution_data["conditionalFormats"]))

    test_runner = TestRunnerProxy(state.reporter)

    if len(student_cond_formats) < len(solution_cond_formats):
        state.report(
            f"There aren't enough conditional format rules defined at `{state.sct_range}`."
        )

    for i, (student_cond_format, solution_cond_format) in enumerate(
            zip(student_cond_formats, solution_cond_formats)):
        ordinal = selectors.get_ord(i + 1)

        selector = dispatcher_selector(student_cond_format,
                                       solution_cond_format)

        test_runner.do_test(
            ExistenceTest(
                *selector("booleanRule"),
                f"The {ordinal} rule is incorrect, expected single color.",
            ))
        test_runner.do_test(
            ExistenceTest(
                *selector("gradientRule"),
                f"The {ordinal} rule is incorrect, expected color scale.",
            ))
        if not test_runner.has_failed:

            def normalize_condition(condition):
                if condition and condition.get("type",
                                               None) == "CUSTOM_FORMULA":
                    condition = copy.deepcopy(condition)
                    condition["values"][0][
                        "userEnteredValue"] = normalize_formula(
                            condition["values"][0]["userEnteredValue"])
                return condition

            tests = [
                EqualityTest(
                    *map(normalize_condition,
                         selector("booleanRule.condition")),
                    f"The condition of the {ordinal} rule is incorrect.",
                ),
                EqualityTest(
                    *selector("booleanRule.format"),
                    f"The format of the {ordinal} rule is incorrect.",
                ),
                EqualityTest(
                    *selector("gradientRule.minpoint"),
                    f"The minpoint of the {ordinal} rule is incorrect.",
                ),
                EqualityTest(
                    *selector("gradientRule.midpoint"),
                    f"The minpoint of the {ordinal} rule is incorrect.",
                ),
                EqualityTest(
                    *selector("gradientRule.maxpoint"),
                    f"The maxpoint of the {ordinal} rule is incorrect.",
                ),
            ]

            test_runner.do_tests(tests)

    nb_issues = len(test_runner.failures)
    if nb_issues > 0:
        _issues_msg = "\n".join(
            [f"- {test.feedback.message}" for test in test_runner.failures])
        _msg = (f"There {'are' if nb_issues > 1 else 'is'} {nb_issues} "
                f"issue{'s' if nb_issues > 1 else ''} with the conditional "
                f"formatting rules:\n\n{_issues_msg}\n")
        state.report(_msg)