Skip to content

Commit c28e8d1

Browse files
committed
feat(tests,cicd): add Github Actions workflow for running tests
1 parent a520b48 commit c28e8d1

File tree

6 files changed

+263
-29
lines changed

6 files changed

+263
-29
lines changed

.github/workflows/test.yml

+74-13
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,92 @@
1-
name: Test
1+
name: Tests
22

33
# Controls when the workflow will run
44
on:
5-
# Triggers the workflow on push or pull request events but only for the master branch
5+
# Triggers the workflow on push or pull request events
66
push:
7-
branches: [ tests ]
87
pull_request:
9-
branches: [ tests ]
108

119
# Allows you to run this workflow manually from the Actions tab
1210
workflow_dispatch:
1311

1412
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
1513
jobs:
16-
17-
# This workflow contains a single job called "tests"
18-
tests:
19-
# The type of runner that the job will run on
20-
runs-on: ubuntu-latest
2114

22-
# Steps represent a sequence of tasks that will be executed as part of the job
15+
windows:
16+
strategy:
17+
fail-fast: false
18+
matrix:
19+
python: [python38, python39]
20+
rfVersion: [3.1.2, 3.2, 3.2.1, 3.2.2]
21+
runs-on: windows-latest
22+
name: Windows (${{ matrix.python }}, robotframework-${{ matrix.rfVersion }})
23+
defaults:
24+
run:
25+
shell: wsl-bash {0}
2326
steps:
24-
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
2527
- uses: actions/checkout@v2
28+
- uses: Vampire/setup-wsl@v1
29+
with:
30+
distribution: Ubuntu-20.04
31+
additional-packages:
32+
dos2unix
33+
- name: Install Nix
34+
run: |
35+
# Nix installer does not support root installation we need a user
36+
useradd test -m
37+
38+
# Create /nix folder with proper permissions
39+
# This is required because otherwise installer gets stuck most likely at running sudo
40+
install -d -m755 -o test -g test /nix
2641
27-
- uses: cachix/install-nix-action@v13
42+
# Download Nix installer
43+
sudo -iu test curl -o ./install-nix.sh -L https://nixos.org/nix/install
44+
45+
# Run installer as single user installation and we do not need a channel
46+
sudo -iu test sh ./install-nix.sh --no-daemon --no-channel-add
47+
- name: Run tests
48+
run: |
49+
# Change line endings
50+
dos2unix default.nix
51+
# Run the tests in project directory where default.nix resides
52+
# We need login shell for that so that .profile is getting read
53+
sudo -iu test sh -c "nix-build $PWD --argstr python ${{ matrix.python }} --argstr rfVersion ${{ matrix.rfVersion }}"
54+
exit $(cat /home/test/result/exitCode)
55+
56+
linux:
57+
strategy:
58+
fail-fast: false
59+
matrix:
60+
python: [python38, python39]
61+
rfVersion: [3.1.2, 3.2, 3.2.1, 3.2.2]
62+
runs-on: ubuntu-latest
63+
name: Linux (${{ matrix.python }}, robotframework-${{ matrix.rfVersion }})
64+
steps:
65+
- uses: actions/checkout@v2
66+
- name: Install Nix
67+
uses: cachix/install-nix-action@v13
2868
with:
2969
nix_path: nixpkgs=channel:nixos-unstable
70+
- name: Run tests
71+
run: |
72+
nix-build --argstr python ${{ matrix.python }} --argstr rfVersion ${{ matrix.rfVersion }}
73+
exit $(cat ./result/exitCode)
3074
31-
- run: nix-shell --argstr cmd "invoke test --in-nix" --argstr python python37 --argstr rfVersion 3.0.4
75+
macos:
76+
strategy:
77+
fail-fast: false
78+
matrix:
79+
python: [python38, python39]
80+
rfVersion: [3.1.2, 3.2, 3.2.1, 3.2.2]
81+
runs-on: macos-latest
82+
name: MacOS (${{ matrix.python }}, robotframework-${{ matrix.rfVersion }})
83+
steps:
84+
- uses: actions/checkout@v2
85+
- name: Install Nix
86+
uses: cachix/install-nix-action@v13
87+
with:
88+
nix_path: nixpkgs=channel:nixos-unstable
89+
- name: Run tests
90+
run: |
91+
nix-build --argstr python ${{ matrix.python }} --argstr rfVersion ${{ matrix.rfVersion }}
92+
exit $(cat ./result/exitCode)

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ dist
1313
venv
1414
.coverage
1515
htmlcov
16-
green-junit.xml
16+
green-junit.xml
1717
tests/resources/green-junit-example_robot_output.xml
1818
example/results_robot_output.xml
1919
example/results.json
2020
.vscode
21+
/result

README.md

+37
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,43 @@ and the task file [`tasks.py`](https://github.com/eficode/robotframework-oxygen/
109109

110110
[Read the developer guide on how to write your own handler](DEVGUIDE.md)
111111

112+
# Developing Oxygen with Nix
113+
114+
Nix is being used in this project for building development environments with capability of running bulk tests across multiple python versions and multiple Robot Framework versions.
115+
116+
## Requirements
117+
118+
- Nix (https://nixos.org/download.html#nix-quick-install)
119+
120+
## Development environment
121+
122+
This opens bash shell in current terminal window, with latest python 3.9 and Robot Framework 3.2.2.
123+
```
124+
$ nix-shell --argstr python python39 --argstr rfVersion 3.2.2
125+
```
126+
Now you can run the tests, for example:
127+
```
128+
$ invoke test --in-nix
129+
$ invoke utest --in-nix
130+
$ invoke atest
131+
```
132+
133+
To exit the environment/shell type `<Ctrl+d>` or:
134+
```
135+
$ exit
136+
```
137+
138+
## Bulk tests
139+
140+
This command tests all currently supported combinations of Python and Robot Framework.
141+
```
142+
$ nix-build test.nix
143+
```
144+
It should run for few minutes, and if all tests pass, the output will be:
145+
```
146+
Overall tests state: ok
147+
```
148+
112149
# License
113150

114151
Details of project licensing can be found in the [LICENSE](LICENSE) file in the project repository.

default.nix

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
{ nixpkgsBranch ? "release-21.05"
2+
, nixpkgs ? "https://github.com/NixOS/nixpkgs/archive/refs/heads/${nixpkgsBranch}.tar.gz"
3+
, python ? "python39"
4+
, rfVersion ? "3.2.2"
5+
, path ? toString ./.
6+
, cmd ? "invoke test --in-nix" }:
7+
let
8+
pkgs = import (fetchTarball nixpkgs) { };
9+
in
10+
with pkgs;
11+
with lib;
12+
let
13+
mach-nix = import (builtins.fetchGit {
14+
url = "https://github.com/DavHau/mach-nix/";
15+
ref = "refs/tags/3.3.0";
16+
}) {
17+
inherit pkgs python;
18+
pypiDataRev = "c8393888d97e74f2217aaafae70bf5bc5c913535";
19+
pypiDataSha256 = "0pfivp1w3pdbsamnmmyy4rsnc4klqnmisjzcq0smc4pp908b6sc3";
20+
};
21+
22+
requirementsWithout = names:
23+
let
24+
requirementsFile = names: runCommand "requirements.txt" {
25+
buildInputs = [ gnused ];
26+
} ''
27+
cp "${/. + "${path}/requirements.txt"}" $out
28+
for name in ${toString names}
29+
do
30+
sed -E "/^$name([=<>]|\$)/d" -i $out
31+
done
32+
'';
33+
in
34+
readFile (requirementsFile names);
35+
36+
pname = "robotframework-oxygen";
37+
requirements = ''
38+
${requirementsWithout ["robotframework"]}
39+
robotframework==${rfVersion}
40+
'';
41+
42+
env = mach-nix.mkPython {
43+
inherit requirements;
44+
};
45+
in
46+
runCommand "${pname}-result" {
47+
buildInputs = [ which coreutils env ];
48+
shellHook = ''
49+
cd ${path}
50+
export PYTHONPATH="$PWD/src:${env}/lib/${env.python.libPrefix}/site-packages"
51+
${cmd}
52+
exitCode=$?
53+
echo -e "\n[${python}][robotframework==${rfVersion}] Exited with $exitCode"
54+
exit $exitCode
55+
'';
56+
} ''
57+
mkdir -p $out
58+
tmpdir="$(mktemp -d -t ${pname}-XXXXXXXXXX)"
59+
trap "rm -rf $tmpdir" EXIT
60+
cp -r ${/. + path} $tmpdir/src
61+
chmod -R u+w $tmpdir
62+
cd $tmpdir/src
63+
export PYTHONPATH="$PWD/src:${env}/lib/${env.python.libPrefix}/site-packages"
64+
export HOME=$tmpdir
65+
echo '{"run":{"shell":"${stdenv.shell}"}}' >$HOME/.invoke.json
66+
exec &> >(tee $out/log)
67+
set +e
68+
${cmd}
69+
exitCode=$?
70+
set -e
71+
echo -e "\n[${python}][robotframework==${rfVersion}] Exited with $exitCode"
72+
echo "$exitCode" > $out/exitCode
73+
echo "${python}" > $out/python
74+
echo "${rfVersion}" > $out/rfVersion
75+
''

tasks.py

+27-15
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
CURDIR = Path.cwd()
88
SRCPATH = CURDIR / 'src'
99
UNIT_TESTS = CURDIR / 'tests'
10+
IN_NIX_HELP = ('Setup environment for use inside Nix. By default PYTHONPATH '
11+
'is being overriden with source path. This flag makes sure '
12+
'that PYTHONPATH is untouched.')
1013

1114
# If you want colored output for the tasks, use `run()` with `pty=True`
1215
# Not on Windows, though -- it'll fail if you have `pty=True`
@@ -35,34 +38,43 @@ def install(context, package=None):
3538
help={
3639
'test': 'Limit unit test execution to specific tests. Must be given '
3740
'multiple times to select several targets. See more: '
38-
'https://github.com/CleanCut/green/blob/master/cli-options.txt#L5'
41+
'https://github.com/CleanCut/green/blob/master/cli-options.txt#L5',
42+
'in_nix': IN_NIX_HELP
3943
})
40-
def utest(context, test=None):
44+
def utest(context, test=None, in_nix=False):
45+
env = {} if in_nix else {'PYTHONPATH': str(SRCPATH)}
4146
run(f'green {" ".join(test) if test else UNIT_TESTS}',
42-
env={'PYTHONPATH': str(SRCPATH)},
47+
env=env,
4348
pty=(not system() == 'Windows'))
44-
run('coverage html')
4549

46-
@task
47-
def coverage(context):
48-
run(f'green -r {str(UNIT_TESTS)}',
49-
env={'PYTHONPATH': str(SRCPATH)},
50-
pty=(not system() == 'Windows'))
50+
@task(help={
51+
'in_nix': IN_NIX_HELP
52+
})
53+
def coverage(context, in_nix=False):
54+
env = {} if in_nix else {'PYTHONPATH': str(SRCPATH)}
55+
run(f'green -r {str(UNIT_TESTS)}',
56+
env=env,
57+
pty=(not system() == 'Windows'))
5158

52-
@task(help={'rf': 'Additional command-line arguments for Robot Framework as '
53-
'single string. E.g: invoke atest --rf "--name my_suite"'})
59+
@task(help={
60+
'rf': 'Additional command-line arguments for Robot Framework as '
61+
'single string. E.g: invoke atest --rf "--name my_suite"'
62+
})
5463
def atest(context, rf=''):
5564
run(f'robot '
56-
f'--pythonpath {str(SRCPATH)} '
65+
f'--pythonpath {str(SRCPATH)}'
5766
f'--dotted '
5867
f'{rf} '
5968
f'--listener oxygen.listener '
6069
f'{str(CURDIR / "tests" / "atest")}',
6170
pty=(not system() == 'Windows'))
6271

63-
@task(pre=[utest, atest])
64-
def test(context):
65-
pass
72+
@task(help={
73+
'in_nix': IN_NIX_HELP
74+
})
75+
def test(context, in_nix=False):
76+
utest(context, in_nix=in_nix)
77+
atest(context)
6678

6779
@task
6880
def doc(context):

test.nix

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{ nixpkgsBranch ? "release-21.05"
2+
, nixpkgs ? "https://github.com/NixOS/nixpkgs/archive/refs/heads/${nixpkgsBranch}.tar.gz"
3+
, pythons ? "python38 python39"
4+
, rfVersions ? "3.1.2 3.2 3.2.1 3.2.2"
5+
, path ? toString ./.
6+
, cmd ? "invoke test --in-nix" }:
7+
let
8+
pkgs = import (fetchTarball nixpkgs) { };
9+
in
10+
with pkgs;
11+
with lib;
12+
let
13+
test = python: rfVersion:
14+
import ./default.nix { inherit nixpkgs python rfVersion path cmd; };
15+
16+
pythons' = splitString " " pythons;
17+
rfVersions' = splitString " " rfVersions;
18+
19+
tests = flatten (map (rfVersion: map (python: test python rfVersion) pythons') rfVersions');
20+
in
21+
runCommand "test-results" {
22+
buildInputs = [ coreutils gnused ];
23+
} (''
24+
mkdir -p $out
25+
echo "python,rfVersion,state,log" >>$out/results.csv
26+
globalState="ok"
27+
'' + (concatMapStringsSep "\n" (test: ''
28+
python="$(cat ${test}/python)"
29+
rfVersion="$(cat ${test}/rfVersion)"
30+
if [ "0" = "$(cat ${test}/exitCode)" ]
31+
then
32+
state="ok"
33+
else
34+
state="error"
35+
globalState="error"
36+
fi
37+
testpath="$out/$python/$rfVersion"
38+
mkdir -p "$testpath"
39+
cp "${test}/exitCode" "$testpath/"
40+
cp "${test}/log" "$testpath/"
41+
echo "$python,$rfVersion,$state,$testpath/log" >>$out/results.csv
42+
'') tests) + ''
43+
44+
echo "$globalState" >$out/state
45+
46+
sed "s/,/\t/g" <(tail -n +2 "$out/results.csv")
47+
echo -e "\nOverall tests state: $globalState"
48+
'')

0 commit comments

Comments
 (0)