diff --git a/mutalyzer/ncbi.py b/mutalyzer/ncbi.py index f131088ae89c6515d80d04e2ba5b11ebee8786c8..62c96c5b8cdf989e229d8d3544e67218d9774ade 100644 --- a/mutalyzer/ncbi.py +++ b/mutalyzer/ncbi.py @@ -3,15 +3,14 @@ Communication with the NCBI. """ -import functools - from Bio import Entrez from .config import settings from .redisclient import client as redis -def _get_link(source_accession, source_db, target_db, match_link_name): +def _get_link(source_accession, source_db, target_db, match_link_name, + source_version=None, match_version=True): """ Retrieve a linked accession number from the NCBI. @@ -22,88 +21,142 @@ def _get_link(source_accession, source_db, target_db, match_link_name): :arg function match_link_name: For each link found, this function is called with the link name (`str`) and it should return `True` iff the link is to be used. - - :returns: Linked accession number (without version number) or `None` if no - link can be found. - :rtype: str + :arg int source_version: Optional version number for `source_accession`. + :arg bool match_version: If `False`, the link does not have to match + `source_version`. + + :returns: Tuple of `(target_accession, target_version)` representing the + link target, or `None` if no link can be found. If `source_version` is + not specified or `match_version` is `False`, `target_version` can be + `None`. + :rtype: tuple(str, int) """ Entrez.email = settings.EMAIL - handle = Entrez.esearch(db=source_db, term=source_accession) + + # If we are currently strictly matching on version, we can try again if + # no result is found. Otherwise, we just report failure. + def fail_or_retry(): + if source_version is None or match_version: + return None + return _get_link(source_accession, source_db, target_db, + match_link_name, source_version=None, + match_version=False) + + if source_version is None: + source = source_accession + else: + source = '%s.%d' % (source_accession, source_version) + + # Find source record. + handle = Entrez.esearch(db=source_db, term=source) try: result = Entrez.read(handle) except Entrez.Parser.ValidationError: - return None + return fail_or_retry() finally: handle.close() try: source_gi = unicode(result['IdList'][0]) except IndexError: - return None + return fail_or_retry() + # Find link from source record to target record. handle = Entrez.elink(dbfrom=source_db, db=target_db, id=source_gi) try: result = Entrez.read(handle) except Entrez.Parser.ValidationError: - return None + return fail_or_retry() finally: handle.close() if not result[0]['LinkSetDb']: - return None + return fail_or_retry() for link in result[0]['LinkSetDb']: if match_link_name(unicode(link['LinkName'])): target_gi = unicode(link['Link'][0]['Id']) break else: - return None + return fail_or_retry() + # Get target record. handle = Entrez.efetch( db=target_db, id=target_gi, rettype='acc', retmode='text') - target_accession = unicode(handle.read()).split('.')[0] + target = unicode(handle.read()).strip().split('.') handle.close() - return target_accession + target_accession = target[0] + target_version = int(target[1]) if source_version is not None else None + return target_accession, target_version -def cache_link(source, target): - """ - Decorator to add caching to link retrieval. - :arg str source: Source database (used to construct cache key). - :arg str target: Target database (used to construct cache key). +def _get_link_cached(forward_key, reverse_key, source_accession, source_db, + target_db, match_link_name, source_version=None, + match_version=True): """ - forward_key = 'ncbi:%s-to-%s:%%s' % (source, target) - reverse_key = 'ncbi:%s-to-%s:%%s' % (target, source) + Version of :func:`_get_link` with caching. - def cache_source_to_target(f): - @functools.wraps(f) - def cached_f(accession): - result = redis.get(forward_key % accession) - if result is not None: - # The empty string is a cached negative result, which we return as - # `None`. - return result or None + :arg str forward_key: Cache key format string for the forward direction. + The source term will be substituted in this template. + :arg str reverse_key: Cache key format string for the reverse direction. + The target term will be substituted in this template. - result = f(accession) - - if result is None: - redis.setex(forward_key % accession, - settings.NEGATIVE_LINK_CACHE_EXPIRATION, '') - return None + The cache value for a negative result (no link found) is the empty string + and expires in `NEGATIVE_LINK_CACHE_EXPIRATION` seconds. + """ + if source_version is not None: + # Query cache for link with version. + target = redis.get(forward_key % + ('%s.%d' % (source_accession, source_version))) + if target == '': + return None + if target: + target_accession, target_version = target.split('.') + return target_accession, int(target_version) + + if source_version is None or not match_version: + # Query cache for link without version. + target = redis.get(forward_key % source_accession) + if target == '': + return None + if target is not None: + return target, None + + # Query NCBI service. + try: + target_accession, target_version = _get_link( + source_accession, source_db, target_db, match_link_name, + source_version=source_version, match_version=match_version) + except TypeError: + # No link was found. + if source_version is not None: + # Store a negative forward link with version. + redis.setex(forward_key % + ('%s.%d' % (source_accession, source_version)), + settings.NEGATIVE_LINK_CACHE_EXPIRATION, '') + if source_version is None or not match_version: + # Store a negative forward link without version. + redis.setex(forward_key % source_accession, + settings.NEGATIVE_LINK_CACHE_EXPIRATION, '') + return None - # We store the resulting link in both directions. - redis.set(forward_key % accession, result) - redis.set(reverse_key % result, accession) - return result + # Store the link without version in both directions. + redis.set(forward_key % source_accession, target_accession) + redis.set(reverse_key % target_accession, source_accession) - return cached_f + if source_version is not None and target_version is not None: + # Store the link with version in both directions. + redis.set(forward_key % ('%s.%d' % (source_accession, source_version)), + '%s.%d' % (target_accession, target_version)) + redis.set(reverse_key % ('%s.%d' % (target_accession, target_version)), + '%s.%d' % (source_accession, source_version)) - return cache_source_to_target + return target_accession, target_version -@cache_link('transcript', 'protein') -def transcript_to_protein(transcript_accession): +def transcript_to_protein(transcript_accession, transcript_version=None, + match_version=True): """ Try to find the protein linked to a transcript. @@ -113,18 +166,26 @@ def transcript_to_protein(transcript_accession): :arg str transcript_accession: Accession number of the transcript for which we want to find the protein (without version number). - - :returns: Accession number of a protein (without version number) or `None` - if no link can be found. - :rtype: str + :arg int transcript_version: Transcript version number. Please provide + this if available, also if it does not need to match. This will enrich + the cache. + :arg bool match_version: If `False`, the link does not have to match + `transcript_version`. + + :returns: Tuple of `(protein_accession, protein_version)` representing the + linked protein, or `None` if no link can be found. If `match_version` is + `False`, `protein_version` can be `None`. TODO: can or will? + :rtype: tuple(str, int) """ - return _get_link( + return _get_link_cached( + 'ncbi:transcript-to-protein:%s', 'ncbi:protein-to-transcript:%s', transcript_accession, 'nucleotide', 'protein', - lambda link: link in ('nuccore_protein', 'nuccore_protein_cds')) + lambda link: link in ('nuccore_protein', 'nuccore_protein_cds'), + source_version=transcript_version, match_version=match_version) -@cache_link('protein', 'transcript') -def protein_to_transcript(protein_accession): +def protein_to_transcript(protein_accession, protein_version=None, + match_version=True): """ Try to find the transcript linked to a protein. @@ -134,11 +195,14 @@ def protein_to_transcript(protein_accession): :arg str protein_accession: Accession number of the protein for which we want to find the transcript (without version number). + TODO :returns: Accession number of a transcript (without version number) or `None` if no link can be found. :rtype: str """ - return _get_link( + return _get_link_cached( + 'ncbi:protein-to-transcript:%s', 'ncbi:transcript-to-protein:%s', protein_accession, 'protein', 'nucleotide', - lambda link: link == 'protein_nuccore_mrna') + lambda link: link == 'protein_nuccore_mrna', + source_version=protein_version, match_version=match_version) diff --git a/mutalyzer/parsers/genbank.py b/mutalyzer/parsers/genbank.py index 5312a1b5996106223c44809e1952f2d6be5d56c9..be3badbdbbc0900910810b07060370bfeb8d27ac 100644 --- a/mutalyzer/parsers/genbank.py +++ b/mutalyzer/parsers/genbank.py @@ -220,8 +220,14 @@ class GBparser(): i.proteinLink = i.protein_id.split('.')[0] #if else : # Tag an mRNA with the protein id too. - i.proteinLink = \ - ncbi.transcript_to_protein(i.transcript_id.split('.')[0]) + accession, version = i.transcript_id.split('.') + protein = ncbi.transcript_to_protein( + accession, int(version), match_version=False) + if protein is None: + i.proteinLink = None + else: + # We ignore the version. + i.proteinLink = protein[0] i.positionList = self.__locationList2posList(i) i.location = self.__location2pos(i.location) #FIXME #if not i.positionList : # FIXME ??? diff --git a/tests/fixtures.py b/tests/fixtures.py index a3f5e363bfdf73d4ab65b724863c14995079b472..870331f86254165a066d73258427eff5c3c2fbd4 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -73,6 +73,35 @@ def available_references(): return yaml.safe_load(f) +def _add_links(settings, links): + """ + Add transcript-protein links to the cache. + """ + for transcript, protein in links: + if transcript is not None: + key = 'ncbi:transcript-to-protein:%s' % transcript + if protein is not None: + redis.set(key, protein) + if '.' in transcript: + key = key.rsplit('.', 1)[0] + redis.set(key, protein.rsplit('.', 1)[0]) + else: + redis.setex(key, + settings.NEGATIVE_LINK_CACHE_EXPIRATION, + '') + if protein is not None: + key = 'ncbi:protein-to-transcript:%s' % protein + if transcript is not None: + redis.set(key, transcript) + if '.' in protein: + key = key.rsplit('.', 1)[0] + redis.set(key, transcript.rsplit('.', 1)[0]) + else: + redis.setex(key, + settings.NEGATIVE_LINK_CACHE_EXPIRATION, + '') + + @pytest.fixture def references(request, settings, db, available_references): try: @@ -99,23 +128,7 @@ def references(request, settings, db, available_references): references.append(Reference( accession, entry['checksum'], geninfo_identifier=geninfo_id)) - for transcript_accession, protein_accession in entry.get('links', []): - if transcript_accession is not None: - key = 'ncbi:transcript-to-protein:%s' % transcript_accession - if protein_accession is not None: - redis.set(key, protein_accession) - else: - redis.setex(key, - settings.NEGATIVE_LINK_CACHE_EXPIRATION, - '') - if protein_accession is not None: - key = 'ncbi:protein-to-transcript:%s' % protein_accession - if transcript_accession is not None: - redis.set(key, transcript_accession) - else: - redis.setex(key, - settings.NEGATIVE_LINK_CACHE_EXPIRATION, - '') + _add_links(settings, entry.get('links', [])) db.session.add_all(references) db.session.commit() @@ -123,6 +136,17 @@ def references(request, settings, db, available_references): return references +@pytest.fixture +def links(request, settings, db, available_references): + try: + links = request.param + except AttributeError: + return [] + + _add_links(settings, links) + return links + + @pytest.fixture def hg19(db): """ @@ -573,3 +597,63 @@ def hg19_transcript_mappings(db, hg19): version=3)) db.session.commit() + + +def with_references(*references): + """ + Convenience decorator for parameterizing tests with reference fixtures. + + Allows us to write: + + @with_references('NM_004006.1', 'NM_004006.2') + def test_references(): + pass + + Instead of: + + @pytest.mark.usefixtures('references') + @pytest.mark.parametrize('references', + [['NM_004006.1', 'NM_004006.2']], + ids=['NM_004006.1,NM_004006.2'], + indirect=True) + def test_references(): + pass + + """ + def test_with_references(test): + return pytest.mark.usefixtures('references')( + pytest.mark.parametrize('references', [references], indirect=True, + ids=[','.join(references)])(test)) + return test_with_references + + +def with_links(*links): + """ + Convenience decorator for parameterizing tests with transcript-protein + link fixtures. + + Allows us to write: + + @with_links(('NM_018650', 'NP_061120'), ('NM_027221', None)) + def test_links(): + pass + + Instead of: + + @pytest.mark.usefixtures('links') + @pytest.mark.parametrize('links', + [('NM_018650', 'NP_061120'), + ('NM_027221', None)], + ids=['NM_018650/NP_061120,NM_027221/*'], + indirect=True) + def test_links(): + pass + + """ + def test_with_links(test): + return pytest.mark.usefixtures('links')( + pytest.mark.parametrize( + 'links', [links], indirect=True, + ids=[','.join('/'.join(a or '*' for a in l) + for l in links)])(test)) + return test_with_links diff --git a/tests/test_ncbi.py b/tests/test_ncbi.py index c8df1c6790a13adbd6239b4d6a71ecc5795fb676..2920bc420df661ef750f8d279179446a47802f86 100644 --- a/tests/test_ncbi.py +++ b/tests/test_ncbi.py @@ -5,33 +5,394 @@ Tests for the mutalyzer.ncbi module. from __future__ import unicode_literals +import Bio.Entrez import pytest from mutalyzer import ncbi +from mutalyzer.redisclient import client as redis +from fixtures import with_links -pytestmark = [ - pytest.mark.usefixtures('references'), - pytest.mark.parametrize('references', [['MARK1']], indirect=True) -] +@pytest.fixture +def entrez(request, monkeypatch): + """ + Fixture monkey-patching the NCBI Entrez API to return transcript-protein + links defined in the fixture parameter. -def test_transcript_to_protein(): + The fixture is similar to the :func:`fixtures.links` fixture, but instead + of storing the links in the cache, the API is monkey-patched. """ - Get protein for transcript. + try: + links = request.param + except AttributeError: + return [] + + # We need two-way lookup. + transcript_to_protein = dict(links) + protein_to_transcript = dict((p, t) for t, p in links) + + # Store original methods which should be called as a fallback. + esearch = Bio.Entrez.esearch + elink = Bio.Entrez.elink + efetch = Bio.Entrez.efetch + + # Intermediate Entrez result object which can be parsed with Entrez.read. + class EntrezResult(object): + def __init__(self, result): + self.result = result + + def read(self): + return self.result + + def close(self): + pass + + def mock_esearch(db=None, term=None): + if ((db == 'nucleotide' and term in transcript_to_protein) + or (db == 'protein' and term in protein_to_transcript)): + return EntrezResult({ + 'Count': '1', + 'RetMax': '1', + 'IdList': [term], + 'TranslationSet': [], + 'RetStart': '0', + 'QueryTranslation': '' + }) + return esearch(db=db, term=term) + + def mock_elink(dbfrom=None, db=None, id=None): + if dbfrom == 'nucleotide' and id in transcript_to_protein: + if transcript_to_protein[id] is None: + linkset = [] + else: + linkset = [{'DbTo': 'protein', + 'Link': [{'Id': transcript_to_protein[id]}], + 'LinkName': 'nuccore_protein'}] + return EntrezResult([{ + 'LinkSetDb': linkset, + 'DbFrom': 'nuccore', + 'IdList': [id], + 'LinkSetDbHistory': [], + 'ERROR': [] + }]) + if dbfrom == 'protein' and id in protein_to_transcript: + if protein_to_transcript[id] is None: + linkset = [] + else: + linkset = [{'DbTo': 'nuccore', + 'Link': [{'Id': '568815587'}, + {'Id': '528476600'}, + {'Id': '568815270'}, + {'Id': '528474155'}, + {'Id': '452415518'}, + {'Id': '452405284'}, + {'Id': '383209650'}], + 'LinkName': 'protein_nuccore'}, + {'DbTo': 'nuccore', + 'Link': [{'Id': '4506864'}], + 'LinkName': 'protein_nuccore_cds'}, + {'DbTo': 'nuccore', + 'Link': [{'Id': '48735311'}, + {'Id': '48734961'}, + {'Id': '47682402'}, + {'Id': '18490203'}, + {'Id': '16359050'}, + {'Id': '16306997'}, + {'Id': '15929518'}, + {'Id': '15214938'}, + {'Id': '13528941'}], + 'LinkName': 'protein_nuccore_mgc_refseq'}, + {'DbTo': 'nuccore', + 'Link': [{'Id': protein_to_transcript[id]}], + 'LinkName': 'protein_nuccore_mrna'}] + return EntrezResult([{ + 'LinkSetDb': linkset, + 'DbFrom': 'protein', + 'IdList': [id], + 'LinkSetDbHistory': [], + 'ERROR': [] + }]) + return elink(dbfrom=dbfrom, db=db, id=id) + + def mock_efetch(db=None, id=None, rettype=None, retmode=None): + if ((db == 'nucleotide' and id in transcript_to_protein) + or (db == 'protein' and id in protein_to_transcript)): + if '.' not in id: + id += '.9999' + return EntrezResult(id + '\n') + return efetch(db=db, id=id, rettype=rettype, retmode=retmode) + + def mock_read(result): + return result.read() + + monkeypatch.setattr(Bio.Entrez, 'esearch', mock_esearch) + monkeypatch.setattr(Bio.Entrez, 'elink', mock_elink) + monkeypatch.setattr(Bio.Entrez, 'efetch', mock_efetch) + monkeypatch.setattr(Bio.Entrez, 'read', mock_read) + return links + + +def with_entrez(*links): + """ + Convenience decorator for parameterizing tests with transcript-protein + link fixtures in the Entrez API. + + Similar to :func:`fixtures.with_links`. """ - assert ncbi.transcript_to_protein('NM_018650') == 'NP_061120' + def test_with_entrez(test): + return pytest.mark.usefixtures('entrez')( + pytest.mark.parametrize( + 'entrez', [links], indirect=True, + ids=[','.join('/'.join(a or '*' for a in l) + for l in links)])(test)) + return test_with_entrez -def test_transcript_to_protein_negative(): +@with_entrez(('NM_11111.1', None), + ('NM_11111.2', 'NP_11111.2'), + ('NM_22222.2', None), + ('NM_22222.3', 'NP_22222.3'), + ('NM_33333.4', None), + ('NM_33333.5', 'NP_33333.5'), + ('NM_44444', None), + ('NM_44444.5', None), + ('NM_44444.6', None), + ('NM_55555', 'NP_55555'), + ('NM_55555.6', None), + ('NM_66666', 'NP_66666'), + ('NM_66666.6', 'NP_66666.6'), + ('NM_66666.7', 'NP_66666.7'), + ('NM_66666.8', None), + ('NM_77777', 'NP_77777'), + ('NM_77777.7', 'NP_77777.7'), + ('NM_77777.8', None), + ('NM_88888', None), + ('NM_88888.8', None), + ('NM_88888.9', 'NP_88888.9')) +@with_links(('NM_11111', 'NP_11111'), + ('NM_22222', None), + ('NM_33333.3', 'NP_33333.3'), + ('NM_44444.4', None), + ('NM_55555.5', None), + ('NM_66666.6', None)) +@pytest.mark.parametrize('accession,version,match_version,expected', [ + ('NM_11111', None, False, ('NP_11111', None)), + ('NM_11111', 1, False, ('NP_11111', None)), + ('NM_11111', 1, True, None), + ('NM_11111', 2, False, ('NP_11111', None)), + ('NM_11111', 2, True, ('NP_11111', 2)), + ('NM_22222', None, False, None), + ('NM_22222', 2, False, None), + ('NM_22222', 2, True, None), + ('NM_22222', 3, False, None), + ('NM_22222', 3, True, ('NP_22222', 3)), + ('NM_33333', None, False, ('NP_33333', None)), + ('NM_33333', 3, True, ('NP_33333', 3)), + ('NM_33333', 3, False, ('NP_33333', 3)), + ('NM_33333', 4, True, None), + ('NM_33333', 4, False, ('NP_33333', None)), + ('NM_33333', 5, True, ('NP_33333', 5)), + ('NM_33333', 5, False, ('NP_33333', None)), + ('NM_44444', None, False, None), + ('NM_44444', 4, True, None), + ('NM_44444', 4, False, None), + ('NM_44444', 5, True, None), + ('NM_44444', 5, False, None), + ('NM_44444', 6, True, None), + ('NM_44444', 6, False, None), + ('NM_55555', None, False, ('NP_55555', None)), + ('NM_55555', 5, True, None), + ('NM_55555', 5, False, None), + ('NM_55555', 6, True, None), + ('NM_55555', 6, False, ('NP_55555', None)), + ('NM_66666', None, False, ('NP_66666', None)), + ('NM_66666', 6, True, None), + ('NM_66666', 6, False, None), + ('NM_66666', 7, True, ('NP_66666', 7)), + ('NM_66666', 7, False, ('NP_66666', 7)), + ('NM_66666', 8, True, None), + ('NM_66666', 8, False, ('NP_66666', None)), + ('NM_77777', None, False, ('NP_77777', None)), + ('NM_77777', 7, False, ('NP_77777', 7)), + ('NM_77777', 7, True, ('NP_77777', 7)), + ('NM_77777', 8, False, ('NP_77777', None)), + ('NM_77777', 8, True, None), + ('NM_88888', None, False, None), + ('NM_88888', 8, False, None), + ('NM_88888', 8, True, None), + ('NM_88888', 9, False, ('NP_88888', 9)), + ('NM_88888', 9, True, ('NP_88888', 9))]) +def test_transcript_to_protein(accession, version, match_version, expected): """ - Get no protein for transcript. + Get protein for transcript. + + Both the Entrez API and our cache are fixed with a set of + transcript-protein links. This test is parametrized with a list of + arguments for the :func:`ncbi.transcript_to_protein` function and the + corresponding expected result. """ - assert ncbi.transcript_to_protein('XM_005273133') is None + assert ncbi.transcript_to_protein( + accession, version, match_version) == expected -def test_protein_to_transcript(): +@with_entrez((None, 'NP_11111.1'), + ('NM_11111.2', 'NP_11111.2'), + (None, 'NP_22222.2'), + ('NM_22222.3', 'NP_22222.3'), + (None, 'NP_33333.4'), + ('NM_33333.5', 'NP_33333.5'), + (None, 'NP_44444'), + (None, 'NP_44444.5'), + (None, 'NP_44444.6'), + ('NM_55555', 'NP_55555'), + (None, 'NP_55555.6'), + ('NM_66666', 'NP_66666'), + ('NM_66666.6', 'NP_66666.6'), + ('NM_66666.7', 'NP_66666.7'), + (None, 'NP_66666.8'), + ('NM_77777', 'NP_77777'), + ('NM_77777.7', 'NP_77777.7'), + (None, 'NP_77777.8'), + (None, 'NP_88888'), + (None, 'NP_88888.8'), + ('NM_88888.9', 'NP_88888.9')) +@with_links(('NM_11111', 'NP_11111'), + (None, 'NP_22222'), + ('NM_33333.3', 'NP_33333.3'), + (None, 'NP_44444.4'), + (None, 'NP_55555.5'), + (None, 'NP_66666.6')) +@pytest.mark.parametrize('accession,version,match_version,expected', [ + ('NP_11111', None, False, ('NM_11111', None)), + ('NP_11111', 1, False, ('NM_11111', None)), + ('NP_11111', 1, True, None), + ('NP_11111', 2, False, ('NM_11111', None)), + ('NP_11111', 2, True, ('NM_11111', 2)), + ('NP_22222', None, False, None), + ('NP_22222', 2, False, None), + ('NP_22222', 2, True, None), + ('NP_22222', 3, False, None), + ('NP_22222', 3, True, ('NM_22222', 3)), + ('NP_33333', None, False, ('NM_33333', None)), + ('NP_33333', 3, True, ('NM_33333', 3)), + ('NP_33333', 3, False, ('NM_33333', 3)), + ('NP_33333', 4, True, None), + ('NP_33333', 4, False, ('NM_33333', None)), + ('NP_33333', 5, True, ('NM_33333', 5)), + ('NP_33333', 5, False, ('NM_33333', None)), + ('NP_44444', None, False, None), + ('NP_44444', 4, True, None), + ('NP_44444', 4, False, None), + ('NP_44444', 5, True, None), + ('NP_44444', 5, False, None), + ('NP_44444', 6, True, None), + ('NP_44444', 6, False, None), + ('NP_55555', None, False, ('NM_55555', None)), + ('NP_55555', 5, True, None), + ('NP_55555', 5, False, None), + ('NP_55555', 6, True, None), + ('NP_55555', 6, False, ('NM_55555', None)), + ('NP_66666', None, False, ('NM_66666', None)), + ('NP_66666', 6, True, None), + ('NP_66666', 6, False, None), + ('NP_66666', 7, True, ('NM_66666', 7)), + ('NP_66666', 7, False, ('NM_66666', 7)), + ('NP_66666', 8, True, None), + ('NP_66666', 8, False, ('NM_66666', None)), + ('NP_77777', None, False, ('NM_77777', None)), + ('NP_77777', 7, False, ('NM_77777', 7)), + ('NP_77777', 7, True, ('NM_77777', 7)), + ('NP_77777', 8, False, ('NM_77777', None)), + ('NP_77777', 8, True, None), + ('NP_88888', None, False, None), + ('NP_88888', 8, False, None), + ('NP_88888', 8, True, None), + ('NP_88888', 9, False, ('NM_88888', 9)), + ('NP_88888', 9, True, ('NM_88888', 9))]) +def test_protein_to_transcript(accession, version, match_version, expected): """ Get transcript for protein. + + Both the Entrez API and our cache are fixed with a set of + transcript-protein links. This test is parametrized with a list of + arguments for the :func:`ncbi.transcript_to_protein` function and the + corresponding expected result. + + Fixtures and parameters of this test mirror those of the + `test_transcript_to_protein` test. + """ + assert ncbi.protein_to_transcript( + accession, version, match_version) == expected + + +@with_entrez(('NM_11111', None), + ('NM_22222', 'NP_22222'), + ('NM_33333', None), + ('NM_33333.3', None), + ('NM_44444', None), + ('NM_44444.4', 'NP_44444.4')) +@pytest.mark.parametrize('accession,version,match_version,expected_forward,expected_reverse', [ + ('NM_11111', None, False, [('NM_11111', None)], []), + ('NM_22222', None, False, + [('NM_22222', 'NP_22222')], [('NM_22222', 'NP_22222')]), + ('NM_33333', None, False, [('NM_33333', None)], []), + ('NM_33333', 3, False, [('NM_33333', None), ('NM_33333.3', None)], []), + ('NM_33333', 3, True, [('NM_33333.3', None)], []), + ('NM_44444', None, False, [('NM_44444', None)], []), + ('NM_44444', 4, False, + [('NM_44444', 'NP_44444'), ('NM_44444.4', 'NP_44444.4')], + [('NM_44444', 'NP_44444'), ('NM_44444.4', 'NP_44444.4')]), + ('NM_44444', 4, True, + [('NM_44444', 'NP_44444'), ('NM_44444.4', 'NP_44444.4')], + [('NM_44444', 'NP_44444'), ('NM_44444.4', 'NP_44444.4')])]) +def test_transcript_to_protein_cache(accession, version, match_version, + expected_forward, expected_reverse): + """ + Get protein for transcript and check the resulting cache state. """ - assert ncbi.protein_to_transcript('NP_061120') == 'NM_018650' + ncbi.transcript_to_protein(accession, version, match_version) + + forward = [(key.split(':')[-1], redis.get(key) or None) + for key in redis.keys('ncbi:transcript-to-protein:*')] + assert sorted(forward) == sorted(expected_forward) + + reverse = [(redis.get(key) or None, key.split(':')[-1]) + for key in redis.keys('ncbi:protein-to-transcript:*')] + assert sorted(reverse) == sorted(expected_reverse) + + +@with_entrez((None, 'NP_11111'), + ('NM_22222', 'NP_22222'), + (None, 'NP_33333'), + (None, 'NP_33333.3'), + (None, 'NP_44444'), + ('NM_44444.4', 'NP_44444.4')) +@pytest.mark.parametrize('accession,version,match_version,expected_forward,expected_reverse', [ + ('NP_11111', None, False, [], [(None, 'NP_11111')]), + ('NP_22222', None, False, + [('NM_22222', 'NP_22222')], [('NM_22222', 'NP_22222')]), + ('NP_33333', None, False, [], [(None, 'NP_33333')]), + ('NP_33333', 3, False, [], [(None, 'NP_33333'), (None, 'NP_33333.3')]), + ('NP_33333', 3, True, [], [(None, 'NP_33333.3')]), + ('NP_44444', None, False, [], [(None, 'NP_44444')]), + ('NP_44444', 4, False, + [('NM_44444', 'NP_44444'), ('NM_44444.4', 'NP_44444.4')], + [('NM_44444', 'NP_44444'), ('NM_44444.4', 'NP_44444.4')]), + ('NP_44444', 4, True, + [('NM_44444', 'NP_44444'), ('NM_44444.4', 'NP_44444.4')], + [('NM_44444', 'NP_44444'), ('NM_44444.4', 'NP_44444.4')])]) +def test_protein_to_transcript_cache(accession, version, match_version, + expected_forward, expected_reverse): + """ + Get transcript for protein and check the resulting cache state. + """ + ncbi.protein_to_transcript(accession, version, match_version) + + forward = [(key.split(':')[-1], redis.get(key) or None) + for key in redis.keys('ncbi:transcript-to-protein:*')] + assert sorted(forward) == sorted(expected_forward) + + reverse = [(redis.get(key) or None, key.split(':')[-1]) + for key in redis.keys('ncbi:protein-to-transcript:*')] + assert sorted(reverse) == sorted(expected_reverse) diff --git a/tests/test_parsers_genbank.py b/tests/test_parsers_genbank.py index e491b767fa237802053a488db873099ebca417ed..2248318e5ac7ff3c5080f4c1a413ddc36c833dd1 100644 --- a/tests/test_parsers_genbank.py +++ b/tests/test_parsers_genbank.py @@ -11,6 +11,8 @@ import pytest from mutalyzer.parsers.genbank import GBparser +from fixtures import with_references + @pytest.fixture def parser(): @@ -35,7 +37,7 @@ def test_product_lists_mismatch(parser, products, expected): assert parser._find_mismatch(products) == expected -@pytest.mark.parametrize('references', [['A1BG']], indirect=True) +@with_references('A1BG') def test_only_complete_genes_included(settings, references, parser): """ Incomplete genes from the reference file should be ignored. diff --git a/tests/test_scheduler.py b/tests/test_scheduler.py index 22c20b3c5bd5fcb5beee384b9b2d3b81be47c5f3..fa336f0f98f5ceae04cf7ce7bdd3a51fd592d80a 100644 --- a/tests/test_scheduler.py +++ b/tests/test_scheduler.py @@ -19,6 +19,8 @@ from mutalyzer import File from mutalyzer import output from mutalyzer import Scheduler +from fixtures import with_references + pytestmark = pytest.mark.usefixtures('db') @@ -85,9 +87,7 @@ def test_large_input(): _batch_job_plain_text(variants, expected, 'syntax-checker') -@pytest.mark.usefixtures('references') -@pytest.mark.parametrize('references', [['AB026906.1', 'NM_000059.3']], - indirect=True) +@with_references('AB026906.1', 'NM_000059.3') def test_name_checker(): """ Simple name checker batch job. @@ -212,8 +212,7 @@ def test_name_checker_altered(): _batch_job_plain_text(variants, expected, 'name-checker') -@pytest.mark.usefixtures('references') -@pytest.mark.parametrize('references', [['NM_000059.3']], indirect=True) +@with_references('NM_000059.3') def test_name_checker_skipped(): """ Name checker job with skipped entries. diff --git a/tests/test_services_soap.py b/tests/test_services_soap.py index f1964b302ca799aab096302059127c4f032d027c..5c100eb1e83318a7448cbfe9b75329b9f93488ee 100644 --- a/tests/test_services_soap.py +++ b/tests/test_services_soap.py @@ -20,6 +20,8 @@ import mutalyzer from mutalyzer.services.soap import application from mutalyzer import Scheduler +from fixtures import with_references + @pytest.fixture def server(): @@ -188,8 +190,7 @@ def test_gettranscriptsbygenename_invalid(api): assert not r -@pytest.mark.usefixtures('references') -@pytest.mark.parametrize('references', [['AF230870.1']], indirect=True) +@with_references('AF230870.1') def test_gettranscriptsandinfo_valid(api): """ Running getTranscriptsAndInfo with a valid genomic reference should @@ -203,8 +204,7 @@ def test_gettranscriptsandinfo_valid(api): assert t in names -@pytest.mark.usefixtures('references') -@pytest.mark.parametrize('references', [['AL449423.14']], indirect=True) +@with_references('AL449423.14') def test_gettranscriptsandinfo_restricted_valid(api): """ Running getTranscriptsAndInfo with a valid genomic reference and a @@ -332,9 +332,7 @@ def test_info(api): assert r.version == mutalyzer.__version__ -@pytest.mark.usefixtures('references') -@pytest.mark.parametrize( - 'references', [['AB026906.1', 'AL449423.14', 'NM_003002.2']], indirect=True) +@with_references('AB026906.1', 'AL449423.14', 'NM_003002.2') def test_getcache(output, api): """ Running the getCache method should give us the expected number of @@ -393,8 +391,7 @@ def test_gettranscripts_with_versions(api): assert t in r.string -@pytest.mark.usefixtures('references') -@pytest.mark.parametrize('references', [['NM_003002.2']], indirect=True) +@with_references('NM_003002.2') def test_runmutalyzer(api): """ Just a runMutalyzer test. @@ -432,8 +429,7 @@ def test_runmutalyzer_reference_info_nm(api): assert r.molecule == 'n' -@pytest.mark.usefixtures('references') -@pytest.mark.parametrize('references', [['NM_003002.2']], indirect=True) +@with_references('NM_003002.2') def test_runmutalyzer_reference_info_nm_version(api): """ Get reference info for an NM variant with version. @@ -448,8 +444,7 @@ def test_runmutalyzer_reference_info_nm_version(api): assert r.molecule == 'n' -@pytest.mark.usefixtures('references') -@pytest.mark.parametrize('references', [['LRG_1']], indirect=True) +@with_references('LRG_1') def test_runmutalyzer_reference_info_lrg(api): """ Get reference info for an LRG variant. @@ -461,8 +456,7 @@ def test_runmutalyzer_reference_info_lrg(api): assert r.molecule == 'g' -@pytest.mark.usefixtures('references') -@pytest.mark.parametrize('references', [['NG_012772.1']], indirect=True) +@with_references('NG_012772.1') def test_runmutalyzer_reference_info_ng(api): """ Get reference info for an NG variant without version. @@ -489,8 +483,7 @@ def test_runmutalyzer_reference_info_ng(api): assert r.molecule == 'g' -@pytest.mark.usefixtures('references') -@pytest.mark.parametrize('references', [['NG_009105.1']], indirect=True) +@with_references('NG_009105.1') def test_runmutalyzer_reference_info_ng_version(api): """ Get reference info for an NG variant with version. @@ -505,8 +498,7 @@ def test_runmutalyzer_reference_info_ng_version(api): assert r.molecule == 'g' -@pytest.mark.usefixtures('references') -@pytest.mark.parametrize('references', [['NG_012772.1']], indirect=True) +@with_references('NG_012772.1') def test_runmutalyzer_reference_info_gi(api): """ Get reference info for a GI variant. @@ -521,8 +513,7 @@ def test_runmutalyzer_reference_info_gi(api): assert r.molecule == 'g' -@pytest.mark.usefixtures('references') -@pytest.mark.parametrize('references', [['NM_000143.3']], indirect=True) +@with_references('NM_000143.3') def test_runmutalyzer_exons(api): """ Exon table in runMutalyzer output. @@ -544,10 +535,7 @@ def test_runmutalyzer_exons(api): assert (exon.gStart, exon.gStop, exon.cStart, exon.cStop) == expected_exon -@pytest.mark.usefixtures('references') -@pytest.mark.parametrize( - 'references', [['AB026906.1', 'NM_003002.2', 'AL449423.14']], - indirect=True) +@with_references('AB026906.1', 'NM_003002.2', 'AL449423.14') def test_batchjob(api): """ Submit a batch job. diff --git a/tests/test_variantchecker.py b/tests/test_variantchecker.py index f11590494f070f85220b411ea25242c12d725d4f..1f9cd1c294159e605b0cd3cf10179c557af50ce6 100644 --- a/tests/test_variantchecker.py +++ b/tests/test_variantchecker.py @@ -9,15 +9,14 @@ import pytest from mutalyzer.variantchecker import check_variant +from fixtures import with_references + # Todo: We had a test for checking a variant on a CONTIG RefSeq reference # (NG_005990.1), but instead we should have separate tests for the retriever # module, including a test for fetching a CONTIG RefSeq reference. -pytestmark = pytest.mark.usefixtures('references') - - @pytest.fixture def checker(output): def check(description): @@ -25,7 +24,7 @@ def checker(output): return check -@pytest.mark.parametrize('references', [['AL449423.14']], indirect=True) +@with_references('AL449423.14') def test_deletion_in_frame(output, checker): """ Simple in-frame deletion should give a simple description on protein @@ -41,7 +40,7 @@ def test_deletion_in_frame(output, checker): assert output.getOutput('newProtein') -@pytest.mark.parametrize('references', [['AL449423.14']], indirect=True) +@with_references('AL449423.14') def test_insertion_in_frame(output, checker): """ Simple in-frame insertion should give a simple description on protein @@ -57,7 +56,7 @@ def test_insertion_in_frame(output, checker): assert output.getOutput('newProtein') -@pytest.mark.parametrize('references', [['AL449423.14']], indirect=True) +@with_references('AL449423.14') def test_insertion_list_in_frame(output, checker): """ Simple in-frame insertion of a list should give a simple description @@ -73,7 +72,7 @@ def test_insertion_list_in_frame(output, checker): assert output.getOutput('newProtein') -@pytest.mark.parametrize('references', [['AL449423.14']], indirect=True) +@with_references('AL449423.14') def test_deletion_insertion_in_frame(output, checker): """ Simple in-frame deletion/insertion should give a simple description on @@ -89,7 +88,7 @@ def test_deletion_insertion_in_frame(output, checker): assert output.getOutput('newProtein') -@pytest.mark.parametrize('references', [['AL449423.14']], indirect=True) +@with_references('AL449423.14') def test_deletion_insertion_list_in_frame(output, checker): """ Simple in-frame deletion-insertion of a list should give a simple @@ -105,7 +104,7 @@ def test_deletion_insertion_list_in_frame(output, checker): assert output.getOutput('newProtein') -@pytest.mark.parametrize('references', [['AL449423.14']], indirect=True) +@with_references('AL449423.14') def test_deletion_insertion_in_frame_complete(output, checker): """ Simple in-frame deletion/insertion should give a simple description on @@ -121,7 +120,7 @@ def test_deletion_insertion_in_frame_complete(output, checker): assert output.getOutput('newProtein') -@pytest.mark.parametrize('references', [['AL449423.14']], indirect=True) +@with_references('AL449423.14') def test_deletion_insertion_list_in_frame_complete(output, checker): """ Simple in-frame deletion-insertion of a list should give a simple @@ -138,7 +137,7 @@ def test_deletion_insertion_list_in_frame_complete(output, checker): assert output.getOutput('newProtein') -@pytest.mark.parametrize('references', [['NM_003002.2']], indirect=True) +@with_references('NM_003002.2') def test_est_warning_nm_est(output, checker): """ Warning for EST positioning on NM reference. @@ -148,7 +147,7 @@ def test_est_warning_nm_est(output, checker): assert len(west) == 1 -@pytest.mark.parametrize('references', [['NM_003002.2']], indirect=True) +@with_references('NM_003002.2') def test_no_est_warning_nm_c(output, checker): """ No EST warning for c. positioning on NM reference. @@ -158,7 +157,7 @@ def test_no_est_warning_nm_c(output, checker): assert len(west) == 0 -@pytest.mark.parametrize('references', [['NM_003002.2']], indirect=True) +@with_references('NM_003002.2') def test_no_est_warning_nm_n(output, checker): """ No EST warning for n. positioning on NM reference. @@ -168,7 +167,7 @@ def test_no_est_warning_nm_n(output, checker): assert len(west) == 0 -@pytest.mark.parametrize('references', [['NG_012772.1']], indirect=True) +@with_references('NG_012772.1') def test_est_warning_ng_est(output, checker): """ Warning for EST positioning on NG reference. @@ -178,7 +177,7 @@ def test_est_warning_ng_est(output, checker): assert len(west) == 1 -@pytest.mark.parametrize('references', [['NG_012772.1']], indirect=True) +@with_references('NG_012772.1') def test_no_est_warning_ng_g(output, checker): """ No EST warning for g. positioning on NG reference. @@ -188,7 +187,7 @@ def test_no_est_warning_ng_g(output, checker): assert len(west) == 0 -@pytest.mark.parametrize('references', [['AA010203.1']], indirect=True) +@with_references('AA010203.1') def test_no_est_warning_est_est(output, checker): """ No warning for EST positioning on EST reference. @@ -198,7 +197,7 @@ def test_no_est_warning_est_est(output, checker): assert len(west) == 0 -@pytest.mark.parametrize('references', [['NM_003002.2']], indirect=True) +@with_references('NM_003002.2') def test_roll(output, checker): """ Just a variant where we should roll. @@ -208,7 +207,7 @@ def test_roll(output, checker): assert len(wroll) > 0 -@pytest.mark.parametrize('references', [['NM_003002.2']], indirect=True) +@with_references('NM_003002.2') def test_no_roll(output, checker): """ Just a variant where we cannot roll. @@ -218,7 +217,7 @@ def test_no_roll(output, checker): assert len(wroll) == 0 -@pytest.mark.parametrize('references', [['NM_000088.3']], indirect=True) +@with_references('NM_000088.3') def test_no_roll_splice(output, checker): """ Here we can roll but should not, because it is over a splice site. @@ -230,7 +229,7 @@ def test_no_roll_splice(output, checker): assert len(wroll) == 0 -@pytest.mark.parametrize('references', [['NM_000088.3']], indirect=True) +@with_references('NM_000088.3') def test_partial_roll_splice(output, checker): """ Here we can roll two positions, but should roll only one because @@ -243,7 +242,7 @@ def test_partial_roll_splice(output, checker): assert len(wroll) > 0 -@pytest.mark.parametrize('references', [['NM_000088.3']], indirect=True) +@with_references('NM_000088.3') def test_roll_after_splice(output, checker): """ Here we can roll and should, we stay in the same exon. @@ -253,7 +252,7 @@ def test_roll_after_splice(output, checker): assert len(wroll) > 0 -@pytest.mark.parametrize('references', [['AL449423.14']], indirect=True) +@with_references('AL449423.14') def test_roll_both_ins(output, checker): """ Insertion that rolls should not use the same inserted sequence in @@ -288,7 +287,7 @@ def test_roll_both_ins(output, checker): assert len(output.getMessagesWithErrorCode('WROLLFORWARD')) == 1 -@pytest.mark.parametrize('references', [['AL449423.14']], indirect=True) +@with_references('AL449423.14') def test_roll_reverse_ins(output, checker): """ Insertion that rolls on the reverse strand should not use the same @@ -300,7 +299,7 @@ def test_roll_reverse_ins(output, checker): assert len(output.getMessagesWithErrorCode('WROLLFORWARD')) == 0 -@pytest.mark.parametrize('references', [['AL449423.14']], indirect=True) +@with_references('AL449423.14') def test_roll_message_forward(output, checker): """ Roll warning message should only be shown for currently selected @@ -311,7 +310,7 @@ def test_roll_message_forward(output, checker): assert len(output.getMessagesWithErrorCode('WROLLREVERSE')) == 0 -@pytest.mark.parametrize('references', [['AL449423.14']], indirect=True) +@with_references('AL449423.14') def test_roll_message_reverse(output, checker): """ Roll warning message should only be shown for currently selected @@ -322,7 +321,7 @@ def test_roll_message_reverse(output, checker): assert len(output.getMessagesWithErrorCode('WROLLREVERSE')) == 1 -@pytest.mark.parametrize('references', [['NM_000143.3']], indirect=True) +@with_references('NM_000143.3') def test_ins_cds_start(output, checker): """ Insertion on CDS start boundary should not be included in CDS. @@ -332,7 +331,7 @@ def test_ins_cds_start(output, checker): # Todo: Is this a good test? -@pytest.mark.parametrize('references', [['NM_000143.3']], indirect=True) +@with_references('NM_000143.3') def test_ins_cds_start_after(output, checker): """ Insertion after CDS start boundary should be included in CDS. @@ -342,7 +341,7 @@ def test_ins_cds_start_after(output, checker): # Todo: Is this a good test? -@pytest.mark.parametrize('references', [['NG_012772.1']], indirect=True) +@with_references('NG_012772.1') def test_del_splice_site(output, checker): """ Deletion hitting one splice site should not do a protein prediction. @@ -355,7 +354,7 @@ def test_del_splice_site(output, checker): assert not output.getOutput('newProtein') -@pytest.mark.parametrize('references', [['NG_012772.1']], indirect=True) +@with_references('NG_012772.1') def test_del_exon(output, checker): """ Deletion of an entire exon should be possible. @@ -368,7 +367,7 @@ def test_del_exon(output, checker): assert output.getOutput('newProtein') -@pytest.mark.parametrize('references', [['NG_012772.1']], indirect=True) +@with_references('NG_012772.1') def test_del_exon_exact(output, checker): """ Deletion of exactly an exon should be possible. @@ -381,7 +380,7 @@ def test_del_exon_exact(output, checker): assert output.getOutput('newProtein') -@pytest.mark.parametrize('references', [['NG_012772.1']], indirect=True) +@with_references('NG_012772.1') def test_del_exon_in_frame(output, checker): """ Deletion of an entire exon with length a triplicate should give a @@ -400,7 +399,7 @@ def test_del_exon_in_frame(output, checker): # Todo: assert that protein products indeed have only this difference. -@pytest.mark.parametrize('references', [['NG_012772.1']], indirect=True) +@with_references('NG_012772.1') def test_del_exons(output, checker): """ Deletion of two entire exons should be possible. @@ -413,7 +412,7 @@ def test_del_exons(output, checker): assert output.getOutput('newProtein') -@pytest.mark.parametrize('references', [['NG_012772.1']], indirect=True) +@with_references('NG_012772.1') def test_del_intron(output, checker): """ Deletion of an entire intron should be possible (fusion of remaining @@ -427,7 +426,7 @@ def test_del_intron(output, checker): assert output.getOutput('newProtein') -@pytest.mark.parametrize('references', [['NG_012772.1']], indirect=True) +@with_references('NG_012772.1') def test_del_intron_exact(output, checker): """ Deletion of exactly an intron should be possible (fusion of flanking @@ -444,7 +443,7 @@ def test_del_intron_exact(output, checker): assert not output.getOutput('newProtein') -@pytest.mark.parametrize('references', [['NG_012772.1']], indirect=True) +@with_references('NG_012772.1') def test_del_intron_in_frame(output, checker): """ Deletion of an entire intron should be possible (fusion of remaining @@ -459,7 +458,7 @@ def test_del_intron_in_frame(output, checker): # Todo: assert that protein products indeed have only this difference. -@pytest.mark.parametrize('references', [['NG_012772.1']], indirect=True) +@with_references('NG_012772.1') def test_del_exon_unknown_offsets(output, checker): """ Deletion of an entire exon with unknown offsets should be possible. @@ -480,7 +479,7 @@ def test_del_exon_unknown_offsets(output, checker): # other transcripts? -@pytest.mark.parametrize('references', [['NG_012772.1']], indirect=True) +@with_references('NG_012772.1') def test_del_exon_unknown_offsets_in_frame(output, checker): """ Deletion of an entire exon with unknown offsets and length a @@ -504,7 +503,7 @@ def test_del_exon_unknown_offsets_in_frame(output, checker): # other transcripts? -@pytest.mark.parametrize('references', [['NG_012772.1']], indirect=True) +@with_references('NG_012772.1') def test_del_exon_unknown_offsets_composed(output, checker): """ Deletion of an entire exon with unknown offsets and another composed @@ -525,7 +524,7 @@ def test_del_exon_unknown_offsets_composed(output, checker): # other transcripts? -@pytest.mark.parametrize('references', [['AL449423.14']], indirect=True) +@with_references('AL449423.14') def test_del_exon_unknown_offsets_reverse(output, checker): """ Deletion of an entire exon with unknown offsets should be possible, @@ -546,7 +545,7 @@ def test_del_exon_unknown_offsets_reverse(output, checker): # other transcripts? -@pytest.mark.parametrize('references', [['NM_000143.3']], indirect=True) +@with_references('NM_000143.3') def test_del_exon_transcript_reference(output, checker): """ Deletion of entire exon on a transcript reference should remove the @@ -563,7 +562,7 @@ def test_del_exon_transcript_reference(output, checker): assert output.getOutput('newProtein') -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_ins_seq(output, checker): """ Insertion of a sequence. @@ -574,7 +573,7 @@ def test_ins_seq(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['NG_012337.1']], indirect=True) +@with_references('NG_012337.1') def test_ins_seq_reverse(output, checker): """ Insertion of a sequence on reverse strand. @@ -585,7 +584,7 @@ def test_ins_seq_reverse(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_ins_range(output, checker): """ Insertion of a range. @@ -597,7 +596,7 @@ def test_ins_range(output, checker): assert len(output.getMessagesWithErrorCode('ENOTIMPLEMENTED')) == 0 -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_ins_range_inv(output, checker): """ Insertion of an inverse range. @@ -609,7 +608,7 @@ def test_ins_range_inv(output, checker): assert len(output.getMessagesWithErrorCode('ENOTIMPLEMENTED')) == 0 -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_ins_seq_list(output, checker): """ Insertion of a sequence as a list. @@ -620,7 +619,7 @@ def test_ins_seq_list(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['NG_012337.1']], indirect=True) +@with_references('NG_012337.1') def test_ins_seq_list_reverse(output, checker): """ Insertion of a sequence as a list on reverse strand. @@ -631,7 +630,7 @@ def test_ins_seq_list_reverse(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_ins_range_list(output, checker): """ Insertion of a range as a list. @@ -643,7 +642,7 @@ def test_ins_range_list(output, checker): assert len(output.getMessagesWithErrorCode('ENOTIMPLEMENTED')) == 0 -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_ins_range_inv_list(output, checker): """ Insertion of an inverse range as a list. @@ -655,7 +654,7 @@ def test_ins_range_inv_list(output, checker): assert len(output.getMessagesWithErrorCode('ENOTIMPLEMENTED')) == 0 -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_ins_seq_seq(output, checker): """ Insertion of two sequences. @@ -666,7 +665,7 @@ def test_ins_seq_seq(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['NG_012337.1']], indirect=True) +@with_references('NG_012337.1') def test_ins_seq_seq_reverse(output, checker): """ Insertion of two sequences on reverse strand. @@ -677,7 +676,7 @@ def test_ins_seq_seq_reverse(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_ins_range_range(output, checker): """ Insertion of two ranges. @@ -689,7 +688,7 @@ def test_ins_range_range(output, checker): assert len(output.getMessagesWithErrorCode('ENOTIMPLEMENTED')) == 0 -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_ins_range_range_inv(output, checker): """ Insertion of a range and an inverse range. @@ -701,7 +700,7 @@ def test_ins_range_range_inv(output, checker): assert len(output.getMessagesWithErrorCode('ENOTIMPLEMENTED')) == 0 -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_ins_seq_range(output, checker): """ Insertion of a sequence and a range. @@ -712,7 +711,7 @@ def test_ins_seq_range(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_ins_seq_range_inv(output, checker): """ Insertion of a sequence and an inverse range. @@ -723,7 +722,7 @@ def test_ins_seq_range_inv(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_ins_range_seq(output, checker): """ Insertion of a range and a sequence. @@ -734,7 +733,7 @@ def test_ins_range_seq(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_ins_range_inv_seq(output, checker): """ Insertion of an inverse range and a sequence. @@ -745,7 +744,7 @@ def test_ins_range_inv_seq(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_ins_seq_coding(output, checker): """ Insertion of a sequence (coding). @@ -756,7 +755,7 @@ def test_ins_seq_coding(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_ins_seq_list_coding(output, checker): """ Insertion of a sequence as a list (coding). @@ -767,7 +766,7 @@ def test_ins_seq_list_coding(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_ins_seq_seq_coding(output, checker): """ Insertion of two sequences (coding). @@ -778,7 +777,7 @@ def test_ins_seq_seq_coding(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_ins_range_coding(output, checker): """ Insertion of a range (coding). @@ -787,7 +786,7 @@ def test_ins_range_coding(output, checker): assert len(output.getMessagesWithErrorCode('ENOTIMPLEMENTED')) == 1 -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_ins_range_inv_coding(output, checker): """ Insertion of an inverse range (coding). @@ -796,7 +795,7 @@ def test_ins_range_inv_coding(output, checker): assert len(output.getMessagesWithErrorCode('ENOTIMPLEMENTED')) == 1 -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_ins_range_list_coding(output, checker): """ Insertion of a range as a list (coding). @@ -805,7 +804,7 @@ def test_ins_range_list_coding(output, checker): assert len(output.getMessagesWithErrorCode('ENOTIMPLEMENTED')) == 1 -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_ins_range_inv_list_coding(output, checker): """ Insertion of an inverse range as a list (coding). @@ -814,7 +813,7 @@ def test_ins_range_inv_list_coding(output, checker): assert len(output.getMessagesWithErrorCode('ENOTIMPLEMENTED')) == 1 -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_delins_seq(output, checker): """ Insertion-deletion of a sequence. @@ -825,7 +824,7 @@ def test_delins_seq(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_delins_range(output, checker): """ Insertion-deletion of a range. @@ -837,7 +836,7 @@ def test_delins_range(output, checker): assert len(output.getMessagesWithErrorCode('ENOTIMPLEMENTED')) == 0 -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_delins_range_inv(output, checker): """ Insertion-deletion of an inverse range. @@ -849,7 +848,7 @@ def test_delins_range_inv(output, checker): assert len(output.getMessagesWithErrorCode('ENOTIMPLEMENTED')) == 0 -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_delins_seq_list(output, checker): """ Insertion-deletion of a sequence as a list. @@ -860,7 +859,7 @@ def test_delins_seq_list(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_delins_range_list(output, checker): """ Insertion-deletion of a range as a list. @@ -872,7 +871,7 @@ def test_delins_range_list(output, checker): assert len(output.getMessagesWithErrorCode('ENOTIMPLEMENTED')) == 0 -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_delins_range_inv_list(output, checker): """ Insertion-deletion of an inverse range as a list. @@ -884,7 +883,7 @@ def test_delins_range_inv_list(output, checker): assert len(output.getMessagesWithErrorCode('ENOTIMPLEMENTED')) == 0 -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_delins_seq_seq(output, checker): """ Insertion-deletion of two sequences. @@ -895,7 +894,7 @@ def test_delins_seq_seq(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_delins_range_range(output, checker): """ Insertion-deletion of two ranges. @@ -907,7 +906,7 @@ def test_delins_range_range(output, checker): assert len(output.getMessagesWithErrorCode('ENOTIMPLEMENTED')) == 0 -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_delins_range_inv_range(output, checker): """ Insertion-deletion of an inverse range and a range. @@ -921,7 +920,7 @@ def test_delins_range_inv_range(output, checker): assert len(output.getMessagesWithErrorCode('ENOTIMPLEMENTED')) == 0 -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_delins_seq_range(output, checker): """ Insertion-deletion of a sequence and a range. @@ -932,7 +931,7 @@ def test_delins_seq_range(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_delins_seq_range_inv(output, checker): """ Insertion-deletion of a sequence and an inverse range. @@ -945,7 +944,7 @@ def test_delins_seq_range_inv(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_delins_range_seq(output, checker): """ Insertion-deletion of a range and a sequence. @@ -956,7 +955,7 @@ def test_delins_range_seq(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_delins_range_inv_seq(output, checker): """ Insertion-deletion of an inverse range and a sequence. @@ -969,7 +968,7 @@ def test_delins_range_inv_seq(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_delins_seq_coding(output, checker): """ Insertion-deletion of a sequence (coding). @@ -980,7 +979,7 @@ def test_delins_seq_coding(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_delins_seq_list_coding(output, checker): """ Insertion-deletion of a sequence as a list (coding). @@ -991,7 +990,7 @@ def test_delins_seq_list_coding(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_delins_seq_seq_coding(output, checker): """ Insertion-deletion of two sequences (coding). @@ -1002,7 +1001,7 @@ def test_delins_seq_seq_coding(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_delins_range_coding(output, checker): """ Insertion-deletion of a range (coding). @@ -1011,7 +1010,7 @@ def test_delins_range_coding(output, checker): assert len(output.getMessagesWithErrorCode('ENOTIMPLEMENTED')) == 1 -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_delins_range_inv_coding(output, checker): """ Insertion-deletion of an inverse range (coding). @@ -1020,7 +1019,7 @@ def test_delins_range_inv_coding(output, checker): assert len(output.getMessagesWithErrorCode('ENOTIMPLEMENTED')) == 1 -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_delins_range_list_coding(output, checker): """ Insertion-deletion of a range as a list (coding). @@ -1029,7 +1028,7 @@ def test_delins_range_list_coding(output, checker): assert len(output.getMessagesWithErrorCode('ENOTIMPLEMENTED')) == 1 -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_delins_range_inv_list_coding(output, checker): """ Insertion-deletion of an inverse range as a list (coding). @@ -1047,7 +1046,7 @@ def test_no_reference(output, checker): @pytest.mark.usefixtures('hg19_transcript_mappings') -@pytest.mark.parametrize('references', [['NM_003002.2']], indirect=True) +@with_references('NM_003002.2') def test_chromosomal_positions(output, checker): """ Variants on transcripts in c. notation should have chromosomal positions @@ -1057,7 +1056,7 @@ def test_chromosomal_positions(output, checker): assert output.getIndexedOutput('rawVariantsChromosomal', 0) == ('chr11', '+', [('274G>T', (111959695, 111959695))]) -@pytest.mark.parametrize('references', [['NM_002001.2']], indirect=True) +@with_references('NM_002001.2') def test_ex_notation(output, checker): """ Variant description using EX notation should not crash but deletion of @@ -1067,7 +1066,7 @@ def test_ex_notation(output, checker): assert len(output.getMessagesWithErrorCode('IDELSPLICE')) == 1 -@pytest.mark.parametrize('references', [['LRG_1']], indirect=True) +@with_references('LRG_1') def test_lrg_reference(output, checker): """ We should be able to use LRG reference sequence without error. @@ -1078,7 +1077,7 @@ def test_lrg_reference(output, checker): assert output.getIndexedOutput('genomicDescription', 0) == 'LRG_1:g.6855G>T' -@pytest.mark.parametrize('references', [['NM_002001.2']], indirect=True) +@with_references('NM_002001.2') def test_gi_reference_plain(output, checker): """ Test reference sequence notation with GI number. @@ -1091,7 +1090,7 @@ def test_gi_reference_plain(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['NM_002001.2']], indirect=True) +@with_references('NM_002001.2') def test_gi_reference_prefix(output, checker): """ Test reference sequence notation with GI number and prefix. @@ -1104,7 +1103,7 @@ def test_gi_reference_prefix(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['NM_002001.2']], indirect=True) +@with_references('NM_002001.2') def test_gi_reference_prefix_colon(output, checker): """ Test reference sequence notation with GI number and prefix with colon. @@ -1117,7 +1116,7 @@ def test_gi_reference_prefix_colon(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['NM_002001.2']], indirect=True) +@with_references('NM_002001.2') def test_nop_nm(output, checker): """ Variant on NM without effect should be described as '='. @@ -1130,7 +1129,7 @@ def test_nop_nm(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['DMD']], indirect=True) +@with_references('DMD') def test_nop_ud(output, references, checker): """ Variant on UD without effect should be described as '='. @@ -1144,7 +1143,7 @@ def test_nop_ud(output, references, checker): assert ud + '(DMD_v001):c.=' in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['DPYD']], indirect=True) +@with_references('DPYD') def test_ud_reverse_sequence(output, references, checker): """ Variant on UD from reverse strand should have reverse complement @@ -1159,7 +1158,7 @@ def test_ud_reverse_sequence(output, references, checker): assert ud + '(DPYD_v001):c.85C>T' in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['MARK1']], indirect=True) +@with_references('MARK1') def test_ud_forward_sequence(output, references, checker): """ Variant on UD from forward strand should have forward sequence. @@ -1173,7 +1172,7 @@ def test_ud_forward_sequence(output, references, checker): assert ud + '(MARK1_v001):c.400T>C' in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['chr9_reverse']], indirect=True) +@with_references('chr9_reverse') def test_ud_reverse_range(output, references, checker): """ Variant on UD from reverse strand should have reversed range @@ -1188,7 +1187,7 @@ def test_ud_reverse_range(output, references, checker): assert output.getIndexedOutput('genomicDescription', 0) == ud + ':g.10624_78132del' -@pytest.mark.parametrize('references', [['MARK1']], indirect=True) +@with_references('MARK1') def test_ud_forward_range(output, references, checker): """ Variant on UD from forward strand should have forward range positions. @@ -1201,7 +1200,7 @@ def test_ud_forward_range(output, references, checker): assert output.getIndexedOutput('genomicDescription', 0) == ud + ':g.76614_76629del' -@pytest.mark.parametrize('references', [['chr9_reverse']], indirect=True) +@with_references('chr9_reverse') def test_ud_reverse_del_length(output, references, checker): """ Variant on UD from reverse strand should have reversed range @@ -1217,7 +1216,7 @@ def test_ud_reverse_del_length(output, references, checker): assert output.getIndexedOutput('genomicDescription', 0) == ud + ':g.10624_78132del' -@pytest.mark.parametrize('references', [['DPYD']], indirect=True) +@with_references('DPYD') def test_ud_reverse_roll(output, references, checker): """ Variant on UD from reverse strand should roll the oposite direction. @@ -1238,7 +1237,7 @@ def test_ud_reverse_roll(output, references, checker): assert ud + '(DPYD_v001):c.105del' in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['MARK1']], indirect=True) +@with_references('MARK1') def test_ud_forward_roll(output, references, checker): """ Variant on UD from forward strand should roll the same. @@ -1259,7 +1258,7 @@ def test_ud_forward_roll(output, references, checker): assert ud + '(MARK1_v001):c.401del' in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['AL449423.14']], indirect=True) +@with_references('AL449423.14') def test_deletion_with_sequence_forward_genomic(output, checker): """ Specify the deleted sequence in a deletion. @@ -1270,7 +1269,7 @@ def test_deletion_with_sequence_forward_genomic(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['AL449423.14']], indirect=True) +@with_references('AL449423.14') def test_deletion_with_length_forward_genomic(output, checker): """ Specify the deleted sequence length in a deletion. @@ -1281,7 +1280,7 @@ def test_deletion_with_length_forward_genomic(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['AL449423.14']], indirect=True) +@with_references('AL449423.14') def test_deletion_with_sequence_reverse_coding(output, checker): """ Specify the deleted sequence in a deletion on the reverse strand. @@ -1292,7 +1291,7 @@ def test_deletion_with_sequence_reverse_coding(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['AL449423.14']], indirect=True) +@with_references('AL449423.14') def test_deletion_with_length_reverse_coding(output, checker): """ Specify the deleted sequence length in a deletion on the reverse strand. @@ -1303,7 +1302,7 @@ def test_deletion_with_length_reverse_coding(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_deletion_with_sequence_reverse_ng_coding(output, checker): """ Specify the deleted sequence in a deletion on the reverse strand @@ -1315,7 +1314,7 @@ def test_deletion_with_sequence_reverse_ng_coding(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_deletion_with_length_reverse_ng_coding(output, checker): """ Specify the deleted sequence length in a deletion on the reverse strand @@ -1327,7 +1326,7 @@ def test_deletion_with_length_reverse_ng_coding(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['AB026906.1']], indirect=True) +@with_references('AB026906.1') def test_inversion(output, checker): """ Inversion variant. @@ -1338,7 +1337,7 @@ def test_inversion(output, checker): in output.getOutput('descriptions') -@pytest.mark.parametrize('references', [['NM_000193.2']], indirect=True) +@with_references('NM_000193.2') def test_delins_with_length(output, checker): """ Delins with explicit length of deleted sequence (bug #108). @@ -1347,7 +1346,7 @@ def test_delins_with_length(output, checker): assert 'NM_000193.2(SHH_i001):p.(Lys38Serfs*2)' in output.getOutput('protDescriptions') -@pytest.mark.parametrize('references', [['NG_009105.1']], indirect=True) +@with_references('NG_009105.1') def test_protein_level_description(output, checker): """ Currently protein level descriptions are not implemented. @@ -1356,7 +1355,7 @@ def test_protein_level_description(output, checker): assert len(output.getMessagesWithErrorCode('ENOTIMPLEMENTED')) == 1 -@pytest.mark.parametrize('references', [['NP_064445.1']], indirect=True) +@with_references('NP_064445.1') def test_protein_reference(output, checker): """ Currently protein references are not implemented. @@ -1365,7 +1364,7 @@ def test_protein_reference(output, checker): assert len(output.getMessagesWithErrorCode('ENOTIMPLEMENTED')) == 1 -@pytest.mark.parametrize('references', [['AF230870.1']], indirect=True) +@with_references('AF230870.1') def test_wnomrna_other(output, checker): """ Warning for no mRNA field on other than currently selected transcript @@ -1377,7 +1376,7 @@ def test_wnomrna_other(output, checker): assert len(wnomrna_other) == 1 -@pytest.mark.parametrize('references', [['AF230870.1']], indirect=True) +@with_references('AF230870.1') def test_wnomrna(output, checker): """ Warning for no mRNA field on currently selected transcript should give @@ -1391,7 +1390,7 @@ def test_wnomrna(output, checker): assert len(wnomrna_other) == 1 -@pytest.mark.parametrize('references', [['L41870.1']], indirect=True) +@with_references('L41870.1') def test_mrna_ref_adjacent_exons_warn(output, checker): """ Warning for mRNA reference where exons are not adjacent. @@ -1403,7 +1402,7 @@ def test_mrna_ref_adjacent_exons_warn(output, checker): assert len(w_exon_annotation) == 1 -@pytest.mark.parametrize('references', [['NM_003002.2']], indirect=True) +@with_references('NM_003002.2') def test_mrna_ref_adjacent_exons_no_warn(output, checker): """ No warning for mRNA reference where exons are adjacent. @@ -1413,7 +1412,7 @@ def test_mrna_ref_adjacent_exons_no_warn(output, checker): assert len(w_exon_annotation) == 0 -@pytest.mark.parametrize('references', [['NM_001199.3']], indirect=True) +@with_references('NM_001199.3') def test_fs_no_stop(output, checker): """ Frame shift yielding no stop codon should be described with @@ -1425,7 +1424,7 @@ def test_fs_no_stop(output, checker): assert 'NM_001199.3(BMP1_i001):p.(Gln730Profs*?)' in output.getOutput('protDescriptions') -@pytest.mark.parametrize('references', [['NM_000193.2']], indirect=True) +@with_references('NM_000193.2') def test_ext_no_stop(output, checker): """ Extension yielding no stop codon should be described with @@ -1437,7 +1436,7 @@ def test_ext_no_stop(output, checker): assert 'NM_000193.2(SHH_i001):p.(*463Serext*?)' in output.getOutput('protDescriptions') -@pytest.mark.parametrize('references', [['NM_000193.2']], indirect=True) +@with_references('NM_000193.2') def test_fs_ext_no_stop(output, checker): """ Extension yielding no stop codon should be described with @@ -1449,7 +1448,7 @@ def test_fs_ext_no_stop(output, checker): assert 'NM_000193.2(SHH_i001):p.(*463Cysext*?)' in output.getOutput('protDescriptions') -@pytest.mark.parametrize('references', [['AB026906.1']], indirect=True) +@with_references('AB026906.1') def test_synonymous_p_is(output, checker): """ Synonymous mutation should yield a p.(=) description. @@ -1459,7 +1458,7 @@ def test_synonymous_p_is(output, checker): assert not output.getOutput('newProteinFancy') -@pytest.mark.parametrize('references', [['NM_024426.4']], indirect=True) +@with_references('NM_024426.4') def test_synonymous_p_is_alt_start(output, checker): """ Synonymous mutation should yield a p.(=) description, also with an @@ -1476,7 +1475,7 @@ def test_synonymous_p_is_alt_start(output, checker): assert not output.getOutput('altProteinFancy') -@pytest.mark.parametrize('references', [['AB026906.1']], indirect=True) +@with_references('AB026906.1') def test_start_codon(output, checker): """ Mutation of start codon should yield a p.? description. @@ -1491,7 +1490,7 @@ def test_start_codon(output, checker): assert not output.getOutput('altStart') -@pytest.mark.parametrize('references', [['NM_024426.4']], indirect=True) +@with_references('NM_024426.4') def test_start_codon_alt_start(output, checker): """ Mutation of start codon should yield a p.? description, also with an @@ -1507,7 +1506,7 @@ def test_start_codon_alt_start(output, checker): assert not output.getOutput('altStart') -@pytest.mark.parametrize('references', [['AB026906.1']], indirect=True) +@with_references('AB026906.1') def test_start_codon_yield_start_p_is(output, checker): """ Silent mutation creating new start codon should yield a p.? @@ -1526,7 +1525,7 @@ def test_start_codon_yield_start_p_is(output, checker): assert not output.getOutput('altProteinFancy') -@pytest.mark.parametrize('references', [['NM_024426.4']], indirect=True) +@with_references('NM_024426.4') def test_start_codon_alt_start_yield_start_p_is(output, checker): """ Silent mutation creating new start codon should yield a p.? @@ -1545,7 +1544,7 @@ def test_start_codon_alt_start_yield_start_p_is(output, checker): assert not output.getOutput('altProteinFancy') -@pytest.mark.parametrize('references', [['AB026906.1']], indirect=True) +@with_references('AB026906.1') def test_start_codon_yield_start(output, checker): """ Mutation creating new start codon should yield a p.? description. The @@ -1562,7 +1561,7 @@ def test_start_codon_yield_start(output, checker): assert output.getOutput('altProtein')[0].startswith('M') -@pytest.mark.parametrize('references', [['NM_024426.4']], indirect=True) +@with_references('NM_024426.4') def test_start_codon_alt_start_yield_start(output, checker): """ Mutation creating new start codon should yield a p.? description, also diff --git a/tests/test_website.py b/tests/test_website.py index 57d085c2240c19d7ef9f1b0365b606f7ae00e5d0..b6b0b2f973f39748dd461782c47e048da44e6043 100644 --- a/tests/test_website.py +++ b/tests/test_website.py @@ -18,6 +18,8 @@ from mutalyzer import announce, Scheduler from mutalyzer.db.models import BatchJob from mutalyzer.website import create_app +from fixtures import with_references + # TODO: Tests for /upload. @@ -125,9 +127,7 @@ def test_description_extractor_raw_fastq(website): assert '[5_6insTT;17del;26A>C;35dup]' in r.data -@pytest.mark.usefixtures('references') -@pytest.mark.parametrize( - 'references', [['NM_004006.1', 'NM_004006.2']], indirect=True) +@with_references('NM_004006.1', 'NM_004006.2') def test_description_extractor_refseq(website): """ Submit two accession numbers to the variant description extractor. @@ -247,8 +247,7 @@ def test_checksyntax_invalid(website): assert 'The "^" indicates the position where the error occurred' in r.data -@pytest.mark.usefixtures('references') -@pytest.mark.parametrize('references', [['NM_002001.2']], indirect=True) +@with_references('NM_002001.2') def test_check_valid(website): """ Submit the name checker form with a valid variant. @@ -273,8 +272,7 @@ def test_check_invalid(website): assert 'The "^" indicates the position where the error occurred' in r.data -@pytest.mark.usefixtures('references') -@pytest.mark.parametrize('references', [['NP_064445.1']], indirect=True) +@with_references('NP_064445.1') def test_check_protein_reference(website): """ Submit the name checker form with a protein reference sequence (not @@ -287,8 +285,7 @@ def test_check_protein_reference(website): assert 'Protein reference sequences are not supported' in r.data -@pytest.mark.usefixtures('references') -@pytest.mark.parametrize('references', [['NM_002001.2']], indirect=True) +@with_references('NM_002001.2') def test_check_noninteractive(website): """ Submit the name checker form non-interactively. @@ -304,8 +301,7 @@ def test_check_noninteractive(website): assert 'Raw variant 1: deletion of 1' in r.data -@pytest.mark.usefixtures('references') -@pytest.mark.parametrize('references', [['NG_012772.1']], indirect=True) +@with_references('NG_012772.1') def test_check_interactive_links(website): """ Submitting interactively should have links to transcripts also @@ -427,10 +423,7 @@ def _batch(website, job_type='name-checker', assembly_name_or_alias=None, return r.data -@pytest.mark.usefixtures('references') -@pytest.mark.parametrize( - 'references', [['AB026906.1', 'NM_003002.2', 'AL449423.14']], - indirect=True) +@with_references('AB026906.1', 'NM_003002.2', 'AL449423.14') def test_batch_namechecker(website): """ Submit the batch name checker form. @@ -610,8 +603,7 @@ def test_batch_syntaxchecker_oldstyle(website): header='Input\tStatus') -@pytest.mark.usefixtures('references') -@pytest.mark.parametrize('references', [['AB026906.1']], indirect=True) +@with_references('AB026906.1') def test_batch_namechecker_restriction_sites(website): """ Submit the batch name checker form and see if restriction site effects @@ -703,8 +695,7 @@ def test_annotated_soap_api(website): assert 'Web Service: Mutalyzer' in r.data -@pytest.mark.usefixtures('references') -@pytest.mark.parametrize('references', [['NG_012337.1']], indirect=True) +@with_references('NG_012337.1') def test_getgs(website): """ Test the /getGS interface used by LOVD2. @@ -721,8 +712,7 @@ def test_getgs(website): assert '<input' not in r.data -@pytest.mark.usefixtures('references') -@pytest.mark.parametrize('references', [['NG_012337.1']], indirect=True) +@with_references('NG_012337.1') def test_getgs_coding_multiple_transcripts(website): """ Test the /getGS interface on a coding description and genomic @@ -737,8 +727,7 @@ def test_getgs_coding_multiple_transcripts(website): assert 'description=NG_012337.1' in r.location -@pytest.mark.usefixtures('references') -@pytest.mark.parametrize('references', [['NG_008939.1']], indirect=True) +@with_references('NG_008939.1') def test_getgs_variant_error(website): """ Test the /getGS interface on a variant description with an error. @@ -861,8 +850,7 @@ def test_upload_local_file_invalid(website): assert 'The file could not be parsed.' in r.data -@pytest.mark.usefixtures('references') -@pytest.mark.parametrize('references', [['NM_002001.2']], indirect=True) +@with_references('NM_002001.2') def test_reference(website): """ Test if reference files are cached. @@ -878,8 +866,7 @@ def test_reference(website): assert r.data == bz2.BZ2File(path).read() -@pytest.mark.usefixtures('references') -@pytest.mark.parametrize('references', [['NM_002001.2']], indirect=True) +@with_references('NM_002001.2') def test_reference_head(website): """ Test if reference files are cached, by issuing a HEAD request. @@ -901,8 +888,8 @@ def test_reference_head_none(website): assert r.status_code == 404 -@pytest.mark.usefixtures('references', 'hg19_transcript_mappings') -@pytest.mark.parametrize('references', [['NM_003002.2']], indirect=True) +@pytest.mark.usefixtures('hg19_transcript_mappings') +@with_references('NM_003002.2') def test_bed(website): """ BED track for variant. @@ -913,8 +900,8 @@ def test_bed(website): assert '\t'.join(['chr11', '111959694', '111959695', '274G>T', '0', '+']) in r.data -@pytest.mark.usefixtures('references', 'hg19_transcript_mappings') -@pytest.mark.parametrize('references', [['NM_000132.3']], indirect=True) +@pytest.mark.usefixtures('hg19_transcript_mappings') +@with_references('NM_000132.3') def test_bed_reverse(website): """ BED track for variant on reverse strand.