run_unit_tests.py 4.38 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/env python
#
# run_unit_tests.py - Runs any pyfeeds tests which are present in the project
# repository.
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#


import os.path as op
import            os
import            sys
import            glob

15
from fsl_ci          import  sprun, add_credentials
16
17
18
from fsl_ci.platform import  get_platform_shortcut_if_not_applicable
from fsl_ci.conda    import (load_meta_yaml,
                             get_project_repository_and_revision)
19
20
21
22
23
24
25


def checkout_project_repository_shortcut_if_no_tests(project_dir):
    """Checks out the project source repository - this is done to get a copy
    of the project unit tests/data.
    """
    # The FSLCONDA_REPOSITORY/REVISION vars are honoured if set
26
    repo, rev = get_project_repository_and_revision('meta.yaml')[:2]
27
28
29
30
31

    if (repo is None) or (rev is None):
        print('No repository or revision listed in meta.yaml - aborting test.')
        sys.exit(0)

32
33
34
35
    sprun(f'git clone {repo} {project_dir}')
    sprun(f'git checkout {rev}', cwd=project_dir)

    # If no feedsRun tests can be found, we abort the job
36
    hits = glob.glob(op.join(project_dir, '**', 'feedsRun*'), recursive=True)
37

38
39
40
41
42
43
    if len(hits) == 0:
        print(f'No feedsRun scripts found in project source repository '
              f'({repo}:{rev} - aborting test.')
        sys.exit(0)


44
45
46
def create_test_env(env_dir, build_dir):
    """Create a conda environment to run the tests, and install pyfeeds and
    the package being tested into it.
47
48
    """

49
    pkgname = load_meta_yaml('meta.yaml')['package']['name']
50

51
52
53
54
55
56
57
    # The FSLCONDA_INTENRAL variable is set
    # for internal/private FSL projects, and
    # determines whether we can install
    # dependencies from the internal channel
    internal   = 'FSLCONDA_INTERNAL' in os.environ
    intchannel = os.environ['FSLCONDA_INTERNAL_CHANNEL_URL']
    pubchannel = os.environ['FSLCONDA_PUBLIC_CHANNEL_URL']
58
59
60
61
62
    username   = os.environ.get('FSLCONDA_INTERNAL_CHANNEL_USERNAME', None)
    password   = os.environ.get('FSLCONDA_INTERNAL_CHANNEL_PASSWORD', None)

    if username is not None:
        intchannel = add_credentials(intchannel, username, password)
63
64
65

    if internal: pkgchannels = [intchannel, pubchannel]
    else:        pkgchannels = [pubchannel]
66
67
68

    pkgchannels = [f'-c {c}' for c in pkgchannels]
    pkgchannels = ' '.join(pkgchannels)
69

70
    # Install <pkgname> from local build dir
71
72
    # Install dependencies of <pkgname> from <pkgchannels>
    # Install pyfeeds from <pkgschannel>
73
    sprun(f'conda create -p {env_dir} '
74
75
76
          f'-c {build_dir} {pkgchannels} '
          '-c conda-forge -c defaults '
          f'{pkgname} fsl-base cxx-compiler make fsl-pyfeeds')
77
78
79


def run_tests(project_dir, test_output_dir, env_dir):
80
81
82
83
84
85
86
    """Runs the project tests using pyfeeds. """

    cfg = op.join(project_dir, 'pyfeeds.cfg')
    if op.exists(cfg): cfg = f'-c {cfg}'
    else:              cfg = ''

    commands = []
87
88
    commands.append(f'. activate {env_dir}')
    commands.append(f'export FSLDIR={env_dir}')
89
90
91
92
93
94
95
    commands.append('. $FSLDIR/etc/fslconf/fsl.sh')
    commands.append(f'pyfeeds run -v -k {cfg} '
                    f'-o {test_output_dir} '
                    f'{project_dir}')

    commands = '; '.join(commands)

96
97
    result = sprun(commands, shell=True, check=False)
    return result.returncode
98
99
100
101
102
103
104


def main():
    recipe_name    = os.environ['CI_PROJECT_NAME']
    job_name       = os.environ['CI_JOB_NAME']
    skip_platforms = os.environ.get('FSLCONDA_SKIP_PLATFORM', '')
    skip_platforms = skip_platforms.split()
105
    meta           = load_meta_yaml('meta.yaml')
106
107
108
109
110
111

    # get the platform name, so we know
    # which build directory to install
    # the package from (and abort if
    # this job is not relevant for the
    # project type)
112
    platform  = get_platform_shortcut_if_not_applicable(
113
        meta, recipe_name, job_name, skip_platforms)
114
    build_dir = op.join(os.getcwd(), 'conda_build', f'_{platform}_')
115
116
117
118
119

    # We check out the project source
    # into a directory named with the
    # conda package name. Test outputs
    # are saved to pyfeeds_results
120
121
122
123
    project_dir     = op.abspath(recipe_name)
    test_output_dir = op.abspath('pyfeeds_results')
    env_dir         = op.abspath('test_env')

124
    checkout_project_repository_shortcut_if_no_tests(project_dir)
125
    create_test_env(env_dir, build_dir)
126
    return run_tests(project_dir, test_output_dir, env_dir)
127
128
129
130


if __name__ == '__main__':
    sys.exit(main())