Skip to content

Commit

Permalink
fix docker container symlinks in dev environment, add missing test code
Browse files Browse the repository at this point in the history
  • Loading branch information
dpark01 committed Sep 13, 2019
1 parent 40cf063 commit aaf5efd
Show file tree
Hide file tree
Showing 3 changed files with 204 additions and 3 deletions.
6 changes: 3 additions & 3 deletions docker/install-dev-layer.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
# Must have $INSTALL_PATH and $VIRAL_NGS_PATH defined (from viral-core docker)
set -e -o pipefail

cd /opt/viral-ngs/viral-assemble
VIRAL_ASSEMBLE_PATH=/opt/viral-ngs/viral-assemble

$VIRAL_NGS_PATH/docker/install-conda-dependencies.sh requirements-conda.txt
$VIRAL_NGS_PATH/docker/install-conda-dependencies.sh $VIRAL_ASSEMBLE_PATH/requirements-conda.txt

ln -s assemble test assembly.py $VIRAL_NGS_PATH
ln -s $VIRAL_ASSEMBLE_PATH/assemble $VIRAL_ASSEMBLE_PATH/test $VIRAL_ASSEMBLE_PATH/assembly.py $VIRAL_NGS_PATH
122 changes: 122 additions & 0 deletions test/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
'''utilities for tests'''

__author__ = "[email protected]"

# built-ins
import filecmp
import os
import re
import unittest
import hashlib
import logging

# third-party
import Bio.SeqIO
import pytest

# intra-project
import util.file
from util.misc import available_cpu_count
from tools.samtools import SamtoolsTool

logging.getLogger('botocore').setLevel(logging.WARNING)
logging.getLogger('boto3').setLevel(logging.WARNING)


if 'PYTEST_XDIST_WORKER_COUNT' in os.environ:
_CPUS = 1
else:
_CPUS = available_cpu_count()


def assert_equal_contents(testCase, filename1, filename2):
'Assert contents of two files are equal for a unittest.TestCase'
testCase.assertTrue(filecmp.cmp(filename1, filename2, shallow=False))


def assert_equal_bam_reads(testCase, bam_filename1, bam_filename2):
''' Assert that two bam files are equivalent
This function converts each file to sam (plaintext) format,
without header, since the header can be variable.
Test data should be stored in bam format rather than sam
to save space, and to ensure the bam->sam conversion
is the same for both files.
'''

samtools = SamtoolsTool()

sam_one = util.file.mkstempfname(".sam")
sam_two = util.file.mkstempfname(".sam")

# write the bam files to sam format, without header (no -h)
samtools.view(args=[], inFile=bam_filename1, outFile=sam_one)
samtools.view(args=[], inFile=bam_filename2, outFile=sam_two)

try:
testCase.assertTrue(filecmp.cmp(sam_one, sam_two, shallow=False))
finally:
for fname in [sam_one, sam_two]:
if os.path.exists(fname):
os.unlink(fname)

def assert_md5_equal_to_line_in_file(testCase, filename, checksum_file, msg=None):
''' Compare the checksum of a test file with the expected checksum
stored in a second file
compare md5(test_output.bam) with expected_output.bam.md5:1
'''

hash_md5 = hashlib.md5()
with open(filename, "rb") as f:
for chunk in iter(lambda: f.read(4096), b""):
hash_md5.update(chunk)

expected_checksum = ""
with open(checksum_file, "rb") as f:
expected_checksum = str(f.readline().decode("utf-8"))

expected_checksum = expected_checksum.replace("\r","").replace("\n","")

assert len(expected_checksum) > 0

testCase.assertEqual(hash_md5.hexdigest(), expected_checksum, msg=msg)

@pytest.mark.usefixtures('tmpdir_class')
class TestCaseWithTmp(unittest.TestCase):
'Base class for tests that use tempDir'

def assertEqualContents(self, f1, f2):
assert_equal_contents(self, f1, f2)

def assertEqualFasta(self, f1, f2):
'''Check that two fasta files have the same sequence ids and bases'''
def seqIdPairs(f):
return [(rec.id, rec.seq) for rec in Bio.SeqIO.parse(f, 'fasta')]
self.assertEqual(seqIdPairs(f1), seqIdPairs(f2))

def assertEqualFastaSeqs(self, f1, f2):
'''Check that two fasta files have the same sequence bases (sequence ids may differ)'''
def seqs(f):
return [rec.seq for rec in Bio.SeqIO.parse(f, 'fasta')]
self.assertEqual(seqs(f1), seqs(f2))

def input(self, fname):
'''Return the full filename for a file in the test input directory for this test class'''
return os.path.join(util.file.get_test_input_path(self), fname)

def inputs(self, *fnames):
'''Return the full filenames for files in the test input directory for this test class'''
return [self.input(fname) for fname in fnames]

"""
When "nose" executes python scripts for automated testing, it excludes ones with
the executable bit set (in case they aren't import safe). To prevent any of the
tests in this folder from being silently excluded, assure this bit is not set.
"""


def assert_none_executable():
testDir = os.path.dirname(__file__)
assert all(not os.access(os.path.join(testDir, filename), os.X_OK) for filename in os.listdir(testDir)
if filename.endswith('.py'))
79 changes: 79 additions & 0 deletions test/stubs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import logging
import os
import pytest
import tools


class StubCondaPackage(tools.Tool):

# Skip gathering in all_tool_classes
_skiptest = True

def __init__(
self,
package,
channel="bioconda",
executable=None,
version="",
verifycmd=None,
verifycode=0,
require_executability=True,
env=None,
env_root_path=None,
conda_cache_path=None,
patches=None,
post_install_command=None,
post_install_ret=0,
post_verify_command=None,
post_verify_ret=0
):
self.executable = executable or package
if type(version) == tools.CondaPackageVersion:
self.version = version
else:
self.version = tools.CondaPackageVersion(version)

self.env_path = None
if 'CONDA_PREFIX' in os.environ and len(os.environ['CONDA_PREFIX']):
last_path_component = os.path.basename(os.path.normpath(os.environ['CONDA_PREFIX']))
self.env_path = os.path.dirname(os.environ['CONDA_PREFIX']) if last_path_component == "bin" else os.environ['CONDA_PREFIX']

else:
raise Exception

def is_attempted(self):
return True

def is_installed(self):
return True

@property
def bin_path(self):
return os.path.join(self.env_path, 'bin')

def executable_path(self):
return os.path.join(self.bin_path, self.executable)

def apply_patches(self):
pass

def verify_install(self):
return

def package_available(self):
return True

def uninstall_package(self):
return True

def install_package(self):
return True

def get_installed_version(self):
return self.version

def post_install(self):
pass

def execute(self, cmd, loglevel=logging.DEBUG):
return {}

0 comments on commit aaf5efd

Please sign in to comment.