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

Add coverage options for hatch-test scripts #1477

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions docs/config/internal/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,34 @@ You can also set the number of seconds to wait between retries by setting the `r
retry-delay = 1
```

### Coverage combine arguments

You can define arguments for the coverage [combine](https://coverage.readthedocs.io/en/latest/cmd.html#cmd-combine) command by setting the `combine-args` option, which must be an array of strings. For example, if you wanted to keep the original coverage files so that they are not automatically deleted, you could set the following:

```toml config-example
[tool.hatch.envs.hatch-test]
combine-args = ["--keep"]
```

### Coverage reporting style

You can define the coverage [reporting](https://coverage.readthedocs.io/en/latest/cmd.html#reporting) style by setting the `reporting` option, which must be a string. For example, if you wanted to generate a report in the `html` style, you could set the following:

```toml config-example
[tool.hatch.envs.hatch-test]
reporting = "html"
```
The default reporting style is `report`.

### Coverage reporting arguments

You can define arguments for the coverage [reporting style](#coverage-reporting-style) by setting the `reporting-args` option, which must be an array of strings. For example, if you wanted to show line numbers of statements in each module that were not executed, you could set the following:

```toml config-example
[tool.hatch.envs.hatch-test]
reporting-args = ["--show-missing"]
```

## Customize environment

You can fully alter the behavior of the environment used by the [`test`](../../cli/reference.md#hatch-test) command.
Expand Down
8 changes: 6 additions & 2 deletions src/hatch/cli/test/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,12 @@ def test(

if cover:
for context in app.runner_context([selected_envs[0]]):
context.add_shell_command('cov-combine')
combine_args: list[str] = list(context.env.config.get('combine-args', []))
context.add_shell_command(['cov-combine', *combine_args])

if not cover_quiet:
for context in app.runner_context([selected_envs[0]]):
context.add_shell_command('cov-report')
reporting: str = context.env.config.get('reporting', 'report')
reporting_args: list[str] = list(context.env.config.get('reporting-args', []))
context.env_vars['HATCH_COV_REPORTING_STYLE'] = reporting
context.add_shell_command(['cov-report', *reporting_args])
4 changes: 2 additions & 2 deletions src/hatch/env/internal/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ def get_default_config() -> dict[str, Any]:
'scripts': {
'run': 'pytest{env:HATCH_TEST_ARGS:} {args}',
'run-cov': 'coverage run -m pytest{env:HATCH_TEST_ARGS:} {args}',
'cov-combine': 'coverage combine',
'cov-report': 'coverage report',
'cov-combine': 'coverage combine {args}',
'cov-report': 'coverage {env:HATCH_COV_REPORTING_STYLE:} {args}',
},
'matrix': [{'python': ['3.12', '3.11', '3.10', '3.9', '3.8']}],
}
134 changes: 134 additions & 0 deletions tests/cli/test/test_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,140 @@ def test_legacy_config_enable_parallel(self, hatch, temp_dir, config_file, env_r
'branch = true',
]

def test_combine_args(self, hatch, temp_dir, config_file, env_run, mocker):
config_file.model.template.plugins['default']['tests'] = False
config_file.save()

project_name = 'My.App'

with temp_dir.as_cwd():
result = hatch('new', project_name)

assert result.exit_code == 0, result.output

project_path = temp_dir / 'my-app'
data_path = temp_dir / 'data'
data_path.mkdir()

project = Project(project_path)
config = dict(project.raw_config)
config['tool']['hatch']['envs'] = {'hatch-test': {'combine-args': ['-q', '--keep']}}
project.save_config(config)

with project_path.as_cwd(env_vars={ConfigEnvVars.DATA: str(data_path)}):
result = hatch('test', '--cover')

assert result.exit_code == 0, result.output
assert not result.output

assert env_run.call_args_list == [
mocker.call('coverage run -m pytest -p no:randomly tests', shell=True),
mocker.call('coverage combine -q --keep', shell=True),
mocker.call('coverage report', shell=True),
]

def test_reporting_style(self, hatch, temp_dir, config_file, env_run, mocker):
config_file.model.template.plugins['default']['tests'] = False
config_file.save()

project_name = 'My.App'

with temp_dir.as_cwd():
result = hatch('new', project_name)

assert result.exit_code == 0, result.output

project_path = temp_dir / 'my-app'
data_path = temp_dir / 'data'
data_path.mkdir()

project = Project(project_path)
config = dict(project.raw_config)
config['tool']['hatch']['envs'] = {'hatch-test': {'reporting': 'xml'}}
project.save_config(config)

with project_path.as_cwd(env_vars={ConfigEnvVars.DATA: str(data_path)}):
result = hatch('test', '--cover')

assert result.exit_code == 0, result.output
assert not result.output

assert env_run.call_args_list == [
mocker.call('coverage run -m pytest -p no:randomly tests', shell=True),
mocker.call('coverage combine', shell=True),
mocker.call('coverage xml', shell=True),
]

def test_reporting_args(self, hatch, temp_dir, config_file, env_run, mocker):
config_file.model.template.plugins['default']['tests'] = False
config_file.save()

project_name = 'My.App'

with temp_dir.as_cwd():
result = hatch('new', project_name)

assert result.exit_code == 0, result.output

project_path = temp_dir / 'my-app'
data_path = temp_dir / 'data'
data_path.mkdir()

project = Project(project_path)
config = dict(project.raw_config)
config['tool']['hatch']['envs'] = {'hatch-test': {'reporting-args': ['-m', '--skip-covered']}}
project.save_config(config)

with project_path.as_cwd(env_vars={ConfigEnvVars.DATA: str(data_path)}):
result = hatch('test', '--cover')

assert result.exit_code == 0, result.output
assert not result.output

assert env_run.call_args_list == [
mocker.call('coverage run -m pytest -p no:randomly tests', shell=True),
mocker.call('coverage combine', shell=True),
mocker.call('coverage report -m --skip-covered', shell=True),
]

def test_combine_and_reporting(self, hatch, temp_dir, config_file, env_run, mocker):
config_file.model.template.plugins['default']['tests'] = False
config_file.save()

project_name = 'My.App'

with temp_dir.as_cwd():
result = hatch('new', project_name)

assert result.exit_code == 0, result.output

project_path = temp_dir / 'my-app'
data_path = temp_dir / 'data'
data_path.mkdir()

project = Project(project_path)
config = dict(project.raw_config)
config['tool']['hatch']['envs'] = {
'hatch-test': {
'combine-args': ['a'],
'reporting': 'html',
'reporting-args': ['b'],
}
}
project.save_config(config)

with project_path.as_cwd(env_vars={ConfigEnvVars.DATA: str(data_path)}):
result = hatch('test', '--cover')

assert result.exit_code == 0, result.output
assert not result.output

assert env_run.call_args_list == [
mocker.call('coverage run -m pytest -p no:randomly tests', shell=True),
mocker.call('coverage combine a', shell=True),
mocker.call('coverage html b', shell=True),
]


class TestRandomize:
def test_flag(self, hatch, temp_dir, config_file, env_run, mocker):
Expand Down