"""The rules are well formed and say the same thing everywhere they appear.""" import pytest from conftest import load NAMES = sorted(load('rules.json')['rules']) @pytest.mark.parametrize('name', NAMES) def test_the_two_dims_differ(name, rules): r = rules['rules'][name] assert r['pos_dim'] != r['neg_dim'], f'{name} compares a channel with itself' @pytest.mark.parametrize('name', NAMES) def test_dims_are_in_range(name, rules): r = rules['rules'][name] for d in (r['pos_dim'], r['neg_dim']): assert 0 <= d < 768 @pytest.mark.parametrize('name', NAMES) def test_category_ids_are_coco(name, rules): assert 1 <= rules['rules'][name]['cat_id'] <= 90 def test_category_ids_are_unique(rules): ids = [r['cat_id'] for r in rules['rules'].values()] assert len(set(ids)) == len(ids) @pytest.mark.parametrize('name', NAMES) def test_eval_carries_the_same_rule(name, rules, evaluation): r, e = rules['rules'][name], evaluation['rules'][name] assert (e['pos_dim'], e['neg_dim']) == (r['pos_dim'], r['neg_dim']) assert e['cat_id'] == r['cat_id'] assert e['train_balanced_accuracy'] == r['train_balanced_accuracy'] @pytest.mark.parametrize('name', NAMES) def test_every_rule_beats_chance(name, evaluation): """Balanced accuracy on a balanced subsample; 0.5 is chance for any rate.""" assert evaluation['rules'][name]['balanced_accuracy'] > 0.5 @pytest.mark.parametrize('name', NAMES) def test_scoring_set_is_balanced_and_large_enough(name, evaluation): e = evaluation['rules'][name] assert e['n_balanced'] % 2 == 0 assert e['n_balanced'] >= 40 def test_distribution_matches_the_rules(evaluation): accs = sorted(v['balanced_accuracy'] for v in evaluation['rules'].values()) d = evaluation['distribution'] assert d['n_categories'] == len(accs) assert d['min'] == accs[0] and d['max'] == accs[-1] for t, n in d['at_least'].items(): assert n == sum(a >= float(t) for a in accs) def test_skipped_categories_are_recorded(rules): """Categories dropped for lack of validation images are named, not silent.""" skipped = rules['provenance']['skipped'] assert len(rules['rules']) + len(skipped) == 80 for s in skipped: assert s['val_positives'] < rules['min_val_images']