Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minimal Windows CI with GitHub Action #92

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open
44 changes: 44 additions & 0 deletions .github/workflows/windows-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Windows CI
on: [push, pull_request]

jobs:
ci:
name: Run tests
strategy:
fail-fast: false
matrix:
py: [3.5, 3.6, 3.7, 3.8]
include:
- py: 3.5
tox: py35-coverage
- py: 3.6
tox: py36-coverage
- py: 3.7
tox: py37-coverage
- py: 3.8
tox: py38-coverage
env:
TOXENV: ${{ matrix.tox }}
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v1
with:
python-version: ${{ matrix.py }}
- name: Install tox
run: |
python -m pip install --upgrade pip
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to use the installed/stable pip. Not that important though for now.

pip install tox
- name: Run tests
run: tox
env:
PYTEST_ADDOPTS: '-vv'
- name: Generate coverage report
run: |
.tox/$TOXENV/bin/coverage report -m
.tox/$TOXENV/bin/coverage xml
# TODO: Set secrets.CODECOV_TOKEN from repositroy settings and uncomment this
# - uses: codecov/codecov-action@v1
# with:
# token: ${{ secrets.CODECOV_TOKEN }}
# yml: .codecov.yml
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

10 changes: 6 additions & 4 deletions covimerage/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,10 +149,12 @@ def run(ctx, args, wrap_profile, profile_file, write_data, data_file,
try:
proc = subprocess.Popen(cmd)

def forward_signals(signalnum, stackframe):
"""Forward SIGHUP to the subprocess."""
proc.send_signal(signalnum)
signal.signal(signal.SIGHUP, forward_signals)
# signal.SIGHUP does not exist on Windows
if hasattr(signal, 'SIGHUP'):
def forward_signals(signalnum, stackframe):
"""Forward SIGHUP to the subprocess."""
proc.send_signal(signalnum)
signal.signal(signal.SIGHUP, forward_signals)

try:
exit_code = proc.wait()
Expand Down
55 changes: 31 additions & 24 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
from os.path import normpath
import signal
import subprocess
from subprocess import call
Expand All @@ -12,6 +13,8 @@
from covimerage import DEFAULT_COVERAGE_DATA_FILE, cli, get_version
from covimerage.cli import get_version_message

NEWLINE = '\n' if sys.platform != 'win32' else '\r\n'


def test_dunder_main_run(capfd):
assert call([sys.executable, '-m', 'covimerage']) == 0
Expand Down Expand Up @@ -85,8 +88,11 @@ def test_cli_run_with_args_fd(capfd):
def test_cli_run_subprocess_exception(runner, mocker):
result = runner.invoke(cli.run, [os.devnull])
out = result.output.splitlines()
assert out[-1].startswith("Error: Failed to run ['/dev/null', '--cmd',")
assert '[Errno 13] Permission denied' in out[-1]
assert out[-1].startswith("Error: Failed to run ['%s', '--cmd'," % os.devnull)
expected_message = '[Errno 13] Permission denied'
if sys.platform == 'win32':
expected_message = '[WinError 2] The system cannot find the file specified'
assert expected_message in out[-1]
assert result.exit_code == 1


Expand Down Expand Up @@ -136,7 +142,7 @@ def test_cli_run_args(runner, mocker, devnull, tmpdir):
assert m.call_args[0] == (['printf', '--', '--headless'],)
assert result.output.splitlines() == [
'Running cmd: printf -- --headless (in %s)' % os.getcwd(),
'Parsing profile file /dev/null.',
'Parsing profile file %s.' % os.devnull,
'Not writing coverage file: no data to report!',
'Error: Command exited non-zero: 3.']

Expand Down Expand Up @@ -221,7 +227,7 @@ def test_cli_run_can_skip_writing_data(with_append, runner, tmpdir):
'Parsing profile file %s.' % profile_file,
'Name Stmts Miss Cover',
'----------------------------------------------------------------',
'tests/test_plugin/conditional_function.vim 13 5 62%']
normpath('tests/test_plugin/conditional_function.vim') + ' 13 5 62%']
assert not tmpdir.join(DEFAULT_COVERAGE_DATA_FILE).exists()


Expand Down Expand Up @@ -267,7 +273,7 @@ def test_cli_run_report_fd(capfd, tmpdir, devnull):
assert out.splitlines() == [
'Name Stmts Miss Cover',
'----------------------------------------------------------------',
'tests/test_plugin/conditional_function.vim 13 5 62%']
normpath('tests/test_plugin/conditional_function.vim') + ' 13 5 62%']
assert err.splitlines() == [
'Running cmd: true (in %s)' % str(os.getcwd()),
'Parsing profile file %s.' % tmp_profile_fname,
Expand All @@ -286,13 +292,13 @@ def test_cli_run_report_fd(capfd, tmpdir, devnull):
assert open(ofname).read().splitlines() == [
'Name Stmts Miss Cover',
'----------------------------------------------------------------',
'tests/test_plugin/conditional_function.vim 13 5 62%']
normpath('tests/test_plugin/conditional_function.vim') + ' 13 5 62%']


def test_cli_call(capfd):
assert call(['covimerage', '--version']) == 0
out, err = capfd.readouterr()
assert out == get_version_message() + '\n'
assert out == get_version_message() + NEWLINE

assert call(['covimerage', '--help']) == 0
out, err = capfd.readouterr()
Expand Down Expand Up @@ -329,7 +335,7 @@ def test_cli_call_verbosity_fd(capfd):
out, err = capfd.readouterr()
assert out == ''
assert err.splitlines() == [
'Parsing file: /dev/null',
'Parsing file: %s' % os.devnull,
'source_files: []',
'Not writing coverage file: no data to report!',
'Error: No data to report.']
Expand All @@ -338,7 +344,7 @@ def test_cli_call_verbosity_fd(capfd):
out, err = capfd.readouterr()
assert out == ''
assert err.splitlines() == [
'Parsing file: /dev/null',
'Parsing file: %s' % os.devnull,
'source_files: []',
'Not writing coverage file: no data to report!',
'Error: No data to report.']
Expand All @@ -353,7 +359,7 @@ def test_cli_call_verbosity_fd(capfd):
assert call(['covimerage', '-qq', 'write_coverage', os.devnull]) == 1
out, err = capfd.readouterr()
assert out == ''
assert err == 'Error: No data to report.\n'
assert err == 'Error: No data to report.' + NEWLINE


def test_cli_writecoverage_without_data(runner):
Expand Down Expand Up @@ -490,7 +496,7 @@ def test_report_profile_or_data_file(runner, tmpdir):
'report', '--data-file', os.devnull])
cov_exc = 'CoverageException: Doesn\'t seem to be a coverage.py data file'
assert result.output.splitlines()[-1] == \
'Error: Coverage could not read data_file: /dev/null (%s)' % cov_exc
'Error: Coverage could not read data_file: %s (%s)' % (os.devnull, cov_exc)
assert result.exit_code == 1

with tmpdir.as_cwd():
Expand All @@ -511,12 +517,12 @@ def test_report_profile_or_data_file(runner, tmpdir):
assert result.output.splitlines() == [
'Name Stmts Miss Cover',
'---------------------------------------------------------------',
'tests/test_plugin/merged_conditionals.vim 19 12 37%']
normpath('tests/test_plugin/merged_conditionals.vim') + ' 19 12 37%']
assert result.exit_code == 0


def test_report_rcfile_and_include(tmpdir, runner):
profiled_file = 'tests/test_plugin/conditional_function.vim'
profiled_file = normpath('tests/test_plugin/conditional_function.vim')
profiled_file_content = open(profiled_file, 'r').read()

# Works without rcfile.
Expand Down Expand Up @@ -553,7 +559,7 @@ def test_report_source(runner, tmpdir, devnull):
)
assert result.exit_code == 2

fname = "foo/bar/test.vim"
fname = normpath("foo/bar/test.vim")
tmpdir.join(fname).ensure().write("echom 1")
tmpdir.join("foo/bar/test2.vim").ensure().write("echom 2")
result = runner.invoke(cli.main, ["report", "--source", ".", devnull.name])
Expand Down Expand Up @@ -591,7 +597,7 @@ def test_report_source(runner, tmpdir, devnull):
== [
"Name Stmts Miss Cover",
"---------------------------------------------------------------",
"tests/test_plugin/merged_conditionals.vim 19 12 37%",
normpath("tests/test_plugin/merged_conditionals.vim") + " 19 12 37%",
]
)
assert result.exit_code == 0
Expand All @@ -609,8 +615,8 @@ def test_cli_xml(runner, tmpdir):

with open('coverage.xml') as f:
xml = f.read()
assert 'filename="%s/tests/test_plugin/merged_conditionals.vim' % (
old_cwd) in xml
assert 'filename="%s' % (
old_cwd.join('tests/test_plugin/merged_conditionals.vim')) in xml

# --rcfile is used.
coveragerc = 'customrc'
Expand All @@ -624,8 +630,8 @@ def test_cli_xml(runner, tmpdir):
assert result.exit_code == 0
with open('custom.xml') as f:
xml = f.read()
assert 'filename="%s/tests/test_plugin/merged_conditionals.vim' % (
old_cwd) in xml
assert 'filename="%s' % (
old_cwd.join('tests/test_plugin/merged_conditionals.vim')) in xml

# --rcfile is used.
coveragerc = 'customrc'
Expand Down Expand Up @@ -661,7 +667,7 @@ def test_run_handles_exit_code_from_python_fd(capfd):
'python', '-c', 'print("output"); import sys; sys.exit(42)'])
out, err = capfd.readouterr()
assert 'Error: Command exited non-zero: 42.' in err.splitlines()
assert out == 'output\n'
assert out == 'output' + NEWLINE
assert ret == 42


Expand Down Expand Up @@ -722,7 +728,7 @@ def run_args(profile_file):
'Writing coverage file .coverage_covimerage.',
'Name Stmts Miss Cover',
'----------------------------------------------------------------',
'tests/test_plugin/conditional_function.vim 13 5 62%']
normpath('tests/test_plugin/conditional_function.vim') + ' 13 5 62%']
assert result.exit_code == 0

assert open('.coverage_covimerage').read().startswith(covdata_header)
Expand All @@ -735,7 +741,7 @@ def run_args(profile_file):
'Writing coverage file .coverage_covimerage.',
'Name Stmts Miss Cover',
'----------------------------------------------------------------',
'tests/test_plugin/conditional_function.vim 13 5 62%']
normpath('tests/test_plugin/conditional_function.vim') + ' 13 5 62%']
assert result.exit_code == 0

# Append another profile.
Expand All @@ -753,8 +759,8 @@ def run_args(profile_file):
'Writing coverage file .coverage_covimerage.',
'Name Stmts Miss Cover',
'----------------------------------------------------------------',
'tests/test_plugin/conditional_function.vim 13 5 62%',
'tests/test_plugin/merged_conditionals.vim 19 12 37%',
normpath('tests/test_plugin/conditional_function.vim') + ' 13 5 62%',
normpath('tests/test_plugin/merged_conditionals.vim') + ' 19 12 37%',
'----------------------------------------------------------------',
'TOTAL 32 17 47%']
assert result.exit_code == 0
Expand All @@ -773,6 +779,7 @@ def test_run_report_without_data(tmpdir, runner, devnull):
assert result.exit_code == 1


@pytest.mark.skipif(sys.platform == 'win32', reason='SIGHUP is not available on Windows')
def test_run_forwards_sighup(devnull):
proc = subprocess.Popen([
sys.executable, '-m', 'covimerage', 'run',
Expand Down
3 changes: 2 additions & 1 deletion tests/test_coveragepy.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
import sys

import attr
Expand Down Expand Up @@ -165,7 +166,7 @@ def test_coveragewrapper(coverage_fileobj, devnull):
with pytest.raises(CoverageWrapperException) as excinfo:
CoverageWrapper(data_file=devnull.name)
assert excinfo.value.args == (
'Coverage could not read data_file: /dev/null',)
'Coverage could not read data_file: %s' % os.devnull,)

f = StringIO()
with pytest.raises(CoverageWrapperException) as excinfo:
Expand Down
3 changes: 2 additions & 1 deletion tests/test_main.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import logging
import os
import textwrap

import coverage
Expand Down Expand Up @@ -39,7 +40,7 @@ def test_profile_fname_or_fobj(caplog, devnull):
with caplog.at_level(logging.DEBUG, logger='covimerage'):
Profile(devnull).parse()
msgs = [(r.levelname, r.message) for r in caplog.records]
assert msgs == [('DEBUG', 'Parsing file: /dev/null')]
assert msgs == [('DEBUG', 'Parsing file: %s' % os.devnull)]

fileobj = StringIO('')
with caplog.at_level(logging.DEBUG, logger='covimerage'):
Expand Down
4 changes: 3 additions & 1 deletion tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import os

from covimerage._compat import StringIO


Expand Down Expand Up @@ -27,7 +29,7 @@ def test_get_fname_and_fobj_and_str(devnull):
F = get_fname_and_fobj_and_str
assert F('foo') == ('foo', None, 'foo')
assert F(None) == (None, None, 'None')
assert F(devnull) == ('/dev/null', devnull, '/dev/null')
assert F(devnull) == (os.devnull, devnull, os.devnull)
s = StringIO('')
assert F(s) == (None, s, str(s))

Expand Down