def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.sut = PasiekaRuleStatistics()
        self.cyk_service_mock = create_autospec(CykService)
        self.rule = Rule(Symbol(hash('A')), Symbol(hash('B')), Symbol(hash('C')))
class TestPasiekaRuleStatistics(unittest.TestCase):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.sut = PasiekaRuleStatistics()
        self.cyk_service_mock = create_autospec(CykService)
        self.rule = Rule(Symbol(hash('A')), Symbol(hash('B')), Symbol(hash('C')))

    def test_for_unknown_rule_no_statistics_should_be_provided(self):
        assert_that(self.sut.get_rule_statistics(self.rule, self.cyk_service_mock), is_(None))

    def test_should_be_able_to_add_new_rule(self):
        # Given:
        self.sut.added_new_rule(self.rule, self.cyk_service_mock)

        # When:
        rule_info = self.sut.get_rule_statistics(self.rule, self.cyk_service_mock)

        # Then:
        assert_that(rule_info, is_not(None))
        assert_that(rule_info[0].rule_usage, is_(equal_to(0)))
        assert_that(rule_info[1].left_side_usage, is_(equal_to(0)))

    def two_rules_with_common_parent_setup(self, rule, another_rule):
        # Given:
        self.sut.added_new_rule(rule, self.cyk_service_mock)
        self.sut.added_new_rule(another_rule, self.cyk_service_mock)

        # When:
        self.sut.rule_used(rule, None, self.cyk_service_mock)
        self.sut.rule_used(rule, None, self.cyk_service_mock)
        self.sut.rule_used(another_rule, None, self.cyk_service_mock)

    def test_should_be_able_to_count_rule_usage(self):
        # Given:
        another_rule = Rule(Symbol(hash('A')), Symbol(hash('B')), Symbol(hash('G')))

        # When:
        self.two_rules_with_common_parent_setup(self.rule, another_rule)

        # Then:
        rule_info = self.sut.get_rule_statistics(self.rule, self.cyk_service_mock)
        assert_that(rule_info, is_not(None))
        assert_that(rule_info[0].rule_usage, is_(equal_to(2)))
        assert_that(rule_info[1].left_side_usage, is_(equal_to(3)))

        another_rule_info = self.sut.get_rule_statistics(another_rule, self.cyk_service_mock)
        assert_that(another_rule_info, is_not(None))
        assert_that(another_rule_info[0].rule_usage, is_(equal_to(1)))
        assert_that(another_rule_info[1].left_side_usage, is_(equal_to(3)))

    def test_should_be_able_to_remove_rule(self):
        # Given:
        another_rule = Rule(Symbol(hash('A')), Symbol(hash('B')), Symbol(hash('G')))
        self.two_rules_with_common_parent_setup(self.rule, another_rule)

        # When:
        self.sut.removed_rule(self.rule, self.cyk_service_mock)

        # Then:
        rule_info = self.sut.get_rule_statistics(self.rule, self.cyk_service_mock)
        assert_that(rule_info, is_(None))

        another_rule_info = self.sut.get_rule_statistics(another_rule, self.cyk_service_mock)
        assert_that(another_rule_info, is_not(None))
        assert_that(another_rule_info[0].rule_usage, is_(equal_to(1)))
        assert_that(another_rule_info[1].left_side_usage, is_(equal_to(1)))