def test_complete_intersection_with_exclusion( self, samples): """ Comprehensive exclusion can leave no Samples. """ prj = mock.MagicMock(samples=samples) observed = fetch_samples( prj, selector_attribute="protocol", selector_exclude=list(BASIC_PROTOCOL_NAMES)) _assert_samples([], observed)
def test_empty_intersection_with_inclusion( self, samples, selector_attribute, selector_include): """ Sensitivity and specificity for positive protocol selection. """ prj = mock.MagicMock(samples=samples) observed = fetch_samples( prj, selector_attribute=selector_attribute, selector_include=selector_include) assert set() == set(observed)
def test_empty_intersection_with_exclusion( self, samples, selector_attribute, selector_exclude): """ Empty intersection with selector_exclude means all Samples remain. """ prj = mock.MagicMock(samples=samples) expected = {s.name for s in samples} observed = fetch_samples(prj, selector_attribute=selector_attribute, selector_exclude=selector_exclude) _assert_samples(expected, observed)
def test_complete_intersection_with_inclusion( self, samples): """ Project with Sample set a subset of selector_include has all fetched. """ prj = mock.MagicMock(samples=samples) expected = {s.name for s in samples} inclusion_protocols = list(BASIC_PROTOCOL_NAMES) print("Inclusion protocols: {}".format(inclusion_protocols)) observed = fetch_samples(prj, selector_include=inclusion_protocols) _assert_samples(expected, observed)
def test_partial_intersection_with_exclusion( self, samples, selector_attribute, selector_exclude, expected_sample_names): """ Sensitivity and specificity for negative protocol selection. """ # Mock out the Project instance. prj = mock.MagicMock(samples=samples) # Make the call and the relevant assertions. observed = fetch_samples(prj, selector_attribute=selector_attribute, selector_exclude=selector_exclude) print(expected_sample_names) print(observed) _assert_samples(expected_sample_names, observed)
def test_partial_intersection_with_inclusion(self, samples, selector_attribute, selector_include, expected_sample_names): """ Empty intersection with the selector_include means no Samples. """ # Mock the Project instance. prj = mock.MagicMock(samples=samples) # Debug aid (only visible if failed) print("Grouped sample names (by protocol): {}". format(_group_samples_by_protocol())) print("Inclusion specification: {}".format(selector_include)) # Perform the call under test and make the associated assertions. observed = fetch_samples( prj, selector_attribute=selector_attribute, selector_include=selector_include) _assert_samples(expected_sample_names, observed)
def test_samples_without_protocol_are_not_included( self, samples, selector_attribute, selector_include, expected_names): """ Inclusion does not grab Sample lacking protocol. """ # Note that the expectations fixture isn't used here since this does # not fit the generic framework in which that one applies. prj = mock.MagicMock(samples=samples) # Remove protocol for ATAC-Seq samples. for s in samples: if s[ASSAY_KEY] == "ATAC-Seq": del s[ASSAY_KEY] observed = fetch_samples( prj, selector_attribute=selector_attribute, selector_include=selector_include) _assert_samples(expected_names, observed)
def test_samples_without_protocol_are_not_included( self, samples, selector_attribute, selector_include, expected_names): """ Inclusion does not grab Sample lacking protocol. """ # Note that the expectations fixture isn't used here since this does # not fit the generic framework in which that one applies. prj = mock.MagicMock(samples=samples) # Remove protocol for ATAC-Seq samples. for s in samples: if s.protocol == "ATAC-Seq": delattr(s, "protocol") observed = fetch_samples( prj, selector_attribute=selector_attribute, selector_include=selector_include) _assert_samples(expected_names, observed)
def test_equivalence_with_subproject( self, tmpdir, samples, selector_attribute, selector_include): """ Selection for protocol(s) is like specific subproject. """ sp_name = "atac" confpath = _write_project_files( tmpdir, all_samples=samples, sp_name=sp_name, sp_samples=list(filter(lambda s: s.protocol in selector_include, samples))) try: full_project = Project(confpath) except Exception: anns_file = os.path.join(tmpdir.strpath, METADATA_KEY, "anns.csv") print("Annotations file lines:") with open(anns_file, 'r') as f: print(f.readlines()) raise subproject = Project(confpath, subproject=sp_name) expected = {s.name for s in subproject.samples} observed = fetch_samples(full_project, selector_attribute=selector_attribute, selector_include=selector_include) _assert_samples(expected, observed_samples=observed)
def test_samples_without_protocol_are_not_excluded( self, samples, spare_via_anonymity): """ Negative selection on protocol leaves Samples without protocol. """ # Strategy: specify all of the protocols as exclusions, then allow # the parameterization to specify which are to be "spared" exclusion # by removing the protocol selector_attribute print("Spare input: {}".format(spare_via_anonymity)) # Account for varied argument types, and contextualize the protocol # names with the test case parameterization. That is, vary them as they # were in the creation of the value supplied via the samples fixture. if isinstance(spare_via_anonymity, str): spare_via_anonymity = [spare_via_anonymity] spare_via_anonymity = list(spare_via_anonymity) print("Modified spare: {}".format(spare_via_anonymity)) # Remove the protocols designated for sparing (from selector_exclude). for s in samples: if s.protocol in spare_via_anonymity: delattr(s, "protocol") print("Protocols on samples: {}".format( {s.protocol for s in samples if hasattr(s, "protocol")})) print("Protocols to spare: {}".format(spare_via_anonymity)) print("Non-protocol Samples: {}".format( {s.name for s in samples if not hasattr(s, "protocol")})) # Mock out the project with the updated Sample objects. prj = mock.MagicMock(samples=samples) # Expected names are associated with protocols spared selector_exclude. sample_names_by_protocol = _group_samples_by_protocol() expected_names = set(itertools.chain.from_iterable( sample_names_by_protocol[p] for p in spare_via_anonymity)) # Make the call and relevant assertions. observed = fetch_samples( prj, selector_attribute="protocol", selector_exclude=list(BASIC_PROTOCOL_NAMES)) _assert_samples(expected_names, observed)
def test_samples_without_protocol_are_not_excluded( self, samples, spare_via_anonymity): """ Negative selection on protocol leaves Samples without protocol. """ # Strategy: specify all of the protocols as exclusions, then allow # the parameterization to specify which are to be "spared" exclusion # by removing the protocol selector_attribute print("Spare input: {}".format(spare_via_anonymity)) # Account for varied argument types, and contextualize the protocol # names with the test case parameterization. That is, vary them as they # were in the creation of the value supplied via the samples fixture. if isinstance(spare_via_anonymity, str): spare_via_anonymity = [spare_via_anonymity] spare_via_anonymity = list(spare_via_anonymity) print("Modified spare: {}".format(spare_via_anonymity)) # Remove the protocols designated for sparing (from selector_exclude). for s in samples: if s[ASSAY_KEY] in spare_via_anonymity: del s[ASSAY_KEY] print("Protocols on samples: {}".format( {s.protocol for s in samples if hasattr(s, "protocol")})) print("Protocols to spare: {}".format(spare_via_anonymity)) print("Non-protocol Samples: {}".format( {s.name for s in samples if not hasattr(s, "protocol")})) # Mock out the project with the updated Sample objects. prj = mock.MagicMock(samples=samples) # Expected names are associated with protocols spared selector_exclude. sample_names_by_protocol = _group_samples_by_protocol() expected_names = set(itertools.chain.from_iterable( sample_names_by_protocol[p] for p in spare_via_anonymity)) # Make the call and relevant assertions. observed = fetch_samples( prj, selector_attribute="protocol", selector_exclude=list(BASIC_PROTOCOL_NAMES)) _assert_samples(expected_names, observed)
def test_no_samples(selector_attribute, selector_include, selector_exclude): """ Regardless of filtration, lack of samples means empty collection. """ prj = mock.MagicMock(samples=[]) observed = fetch_samples(prj, selector_attribute=selector_attribute, selector_include=selector_include, selector_exclude=selector_exclude) assert [] == observed
def test_no_filter(selector_attribute, selector_include, selector_exclude, samples): """ Without a filtration mechanism, all Samples are retained. """ prj = mock.MagicMock(samples=samples) assert samples == fetch_samples(prj, selector_attribute=selector_attribute, selector_include=selector_include, selector_exclude=selector_exclude)
def test_only_inclusion_or_exclusion(selector_attribute, selector_include, selector_exclude, samples): """ Only an selector_include or selector_exclude set is permitted. """ prj = mock.MagicMock(samples=samples) with pytest.raises(TypeError): fetch_samples(prj, selector_attribute, selector_include=selector_include, selector_exclude=selector_exclude)
def test_has_attribute(selector_attribute, selector_exclude, samples): """ At least one of the samples has to have the specified selector_attribute. """ prj = mock.MagicMock(samples=samples) with pytest.raises(AttributeError): fetch_samples(prj, selector_attribute=selector_attribute, selector_exclude=selector_exclude)