Skip to content

Commit

Permalink
Version 0.0.1
Browse files Browse the repository at this point in the history
See #3 for commit history.
  • Loading branch information
blueyed committed Oct 15, 2017
1 parent c719b72 commit 1e94207
Show file tree
Hide file tree
Showing 48 changed files with 3,615 additions and 0 deletions.
79 changes: 79 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Python CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-python/ for more details
#
version: 2

common: &common
working_directory: ~/repo
steps:
- checkout
- restore_cache:
keys:
- v1-deps-{{ .Environment.CIRCLE_JOB }}-{{ checksum "setup.py" }}
- v1-deps-
- run: pip install --user tox
- run: ~/.local/bin/tox
- run:
name: upload coverage results for non-checkqa builds
command: |
if [[ "$TOXENV" != checkqa ]]; then
PATH=$HOME/.local/bin:$PATH
# XXX: use bash script?!
pip install --user codecov
coverage xml
coverage report -m
codecov --required -X search gcov pycov -f coverage.xml --flags $CIRCLE_JOB
if [[ "$CIRCLE_JOB" == py36 ]]; then
pip install --user coveralls
coveralls
fi
set +x
fi
- save_cache:
paths:
- .tox
- ~/.cache/pip
key: v1-deps-{{ .Environment.CIRCLE_JOB }}-{{ checksum "setup.py" }}
jobs:
py36:
<<: *common
docker:
- image: circleci/python:3.6
environment:
TOXENV=py36-coverage
py35:
<<: *common
docker:
- image: circleci/python:3.5
environment:
TOXENV=py35-coverage
py34:
<<: *common
docker:
- image: circleci/python:3.4
environment:
TOXENV=py34-coverage
py27:
<<: *common
docker:
- image: circleci/python:2.7
environment:
TOXENV=py27-coverage
checkqa:
<<: *common
docker:
- image: circleci/python:3.6
environment:
TOXENV=checkqa

workflows:
version: 2
test:
jobs:
- py36
- py35
- py34
- py27
- checkqa
7 changes: 7 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[run]
source = .
include = covimerage/*,tests/*
branch = true

[report]
show_missing = true
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build/
100 changes: 100 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
test:
tox -e py36

VIM:=$(shell command -v nvim || echo vim)

test_integration:
tox -e integration

# Fixture generation.
PROFILES_TO_MERGE_COND:=tests/fixtures/merged_conditionals-0.profile \
tests/fixtures/merged_conditionals-1.profile \
tests/fixtures/merged_conditionals-2.profile
fixtures: tests/fixtures/test_plugin.vim.profile
fixtures: tests/fixtures/test_plugin.nvim.profile
fixtures: tests/fixtures/dict_function.profile
fixtures: tests/fixtures/dict_function_with_same_source.profile
fixtures: tests/fixtures/dict_function_with_continued_lines.profile
fixtures: tests/fixtures/dict_function_used_twice.profile
fixtures: tests/fixtures/continued_lines.profile
fixtures: tests/fixtures/conditional_function.profile
fixtures: $(PROFILES_TO_MERGE_COND)

# TODO: cleanup. Should be handled by the generic rule at the bottom.
tests/fixtures/dict_function.profile: tests/test_plugin/dict_function.vim
$(VIM) --noplugin -Nu tests/t.vim --cmd 'let g:prof_fname = "$@"' -c 'source $<' -c q
sed -i 's:^SCRIPT .*/test_plugin:SCRIPT /test_plugin:' $@

tests/fixtures/dict_function_with_same_source.profile: test_plugin/dict_function_with_same_source.vim
$(VIM) --noplugin -Nu tests/t.vim --cmd 'let g:prof_fname = "$@"' -c 'source $<' -c q
sed -i 's:^SCRIPT .*/test_plugin:SCRIPT /test_plugin:' $@

tests/fixtures/test_plugin.vim.profile: test_plugin/autoload/test_plugin.vim
vim --noplugin -Nu tests/t.vim --cmd 'let g:prof_fname = "$@"' -c q

tests/fixtures/test_plugin.nvim.profile: test_plugin/autoload/test_plugin.vim
nvim --noplugin -Nu tests/t.vim --cmd 'let g:prof_fname = "$@"' -c q

PROFILES_TO_MERGE:=tests/fixtures/merge-1.profile tests/fixtures/merge-2.profile
$(PROFILES_TO_MERGE): test_plugin/merged_profiles.vim test_plugin/merged_profiles-init.vim Makefile
$(VIM) -Nu test_plugin/merged_profiles-init.vim -c q
sed -i 's:^SCRIPT .*/test_plugin:SCRIPT /test_plugin:' $(PROFILES_TO_MERGE)

PROFILES_TO_MERGE_COND:=tests/fixtures/merged_conditionals-0.profile \
tests/fixtures/merged_conditionals-1.profile \
tests/fixtures/merged_conditionals-2.profile
$(PROFILES_TO_MERGE_COND): tests/test_plugin/merged_conditionals.vim Makefile
for cond in 0 1 2; do \
$(VIM) --noplugin -Nu tests/t.vim \
--cmd "let g:prof_fname = 'tests/fixtures/merged_conditionals-$$cond.profile'" \
--cmd "let test_conditional = $$cond" \
-c "source $<" -c q; \
done
sed -i 's:^SCRIPT .*/test_plugin:SCRIPT tests/test_plugin:' $(PROFILES_TO_MERGE_COND)

tests/fixtures/%.profile: tests/test_plugin/%.vim Makefile
$(VIM) --noplugin -Nu tests/t.vim --cmd 'let g:prof_fname = "$@"' -c 'source $<' -c q
sed -i 's:^SCRIPT .*/test_plugin:SCRIPT tests/test_plugin:' $@


# Helpers to generate (combined) coverage and show a diff {{{
#
# Use `make coverage-diff` to diff coverage diff to the old state
# (recorded via `make coverage-save`).

MAIN_COVERAGE:=build/coverage

coverage: $(MAIN_COVERAGE)
COVERAGE_FILE=$< coverage report -m

coverage-save: | build
cp -a $(MAIN_COVERAGE) build/coverage.old

coverage-diff: build/covreport.old
coverage-diff: build/covreport.new
coverage-diff:
@diff --color=always -u $^ | /usr/share/git/diff-highlight/diff-highlight | sed 1,3d
@#git --no-pager diff --no-index --color-words build/covreport.old build/covreport.new | sed 1,5d
@# git --no-pager diff --color --no-index build/covreport.old build/covreport.new | sed 1,5d | diff-so-fancy

.PHONY: coverage coverage-save coverage-diff

$(MAIN_COVERAGE): $(shell find covimerage tests -name '*.py') | build
COVERAGE_FILE=$@ tox -e coverage.pytest

build/coverage.old:
$(MAKE) coverage-save

build/covreport.old: build/coverage.old | build
COVERAGE_FILE=$< coverage report -m > $@ || { ret=$$?; cat $@; exit $$ret; }

build/covreport.new: $(MAIN_COVERAGE) | build
COVERAGE_FILE=$< coverage report -m > $@ || { ret=$$?; cat $@; exit $$ret; }
# }}}

tags:
rg --files-with-matches . | ctags --links=no -L-
.PHONY: tags

build:
mkdir -p $@
102 changes: 102 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# covimerage

Generates code coverage information for Vim scripts.

It parses the output from Vim's `:profile` command, and generates data
compatible with [Coverage.py](http://coverage.readthedocs.io/).

**NOTE:** this `develop` branch will be squash-merged into master after some
stabilization (1-2 weeks).

[![CircleCI](https://circleci.com/gh/Vimjas/covimerage.svg?style=svg)](https://circleci.com/gh/Vimjas/covimerage)
[![codecov](https://codecov.io/gh/Vimjas/covimerage/branch/develop/graph/badge.svg)](https://codecov.io/gh/Vimjas/covimerage/branch/develop)

## Installation

You can install covimerage using pip:

```sh
pip install covimerage
```

## Simple usage

You can use `covimerage run` to wrap the call to Neovim/Vim with necessary
boilerplate:

```sh
covimerage run vim -Nu test/vimrc -c 'Vader! test/**'
```

This will write the file `.coverage.covimerage` by default (use `--data-file`
to configure it), which is compatible to Coverage.py.
A report is automatically generated (on stdout).

You can then call `covimerage xml` to create a `coverage.xml` file
(Cobertura-compatible), which tools like [Codecov](https://codecov.io/)'s
`codecov` tool can consume, e.g. via `codecov -f coverage.xml`.

## Manual/advanced usage

### 1. Generate profile information for your Vim script(s)

You have to basically add the following to your tests vimrc:

```vim
profile start /tmp/vim-profile.txt
profile! file ./*
```

This makes Neovim/Vim then write a file with profiling information.

### 2. Call covimerage on the output file(s)

```sh
covimerage write_coverage /tmp/vim-profile.txt
```

This will create a file `.coverage.covimerage` (the default for `--data-file`),
with entries marked for processing by a
[Coverage.py](http://coverage.readthedocs.io/) plugin (provided by
covimerage)).

### 3. Include the covimerage plugin in .coveragerc

When using `coverage` on the generated output (data file), you need to add
the `covimerage` plugin to the `.coveragerc` file (which Coverage.py uses).
This is basically all the `.coveragerc` you will need, but you could use
other settings here (for Coverage.py), e.g. to omit some files:

```
[run]
plugins = covimerage
data_file = .coverage.covimerage
```

### 4. Create the report(s)

You can now call e.g. `coverage report -m`, and you should be able to use
coverage reporting platforms like <https://codecov.io/> or
<https://coveralls.io>, which are basically using `coverage xml`.

## Reference implementation

- [Neomake](https://github.com/neomake/neomake) is the first adopter of this.
It has an advanced test setup (including Docker based builds), and looking at
tis setup could be helpful when setting up covimerage for your
plugin/project.

- [Neomake's coverage report on codecov.io](https://codecov.io/gh/neomake/neomake/tree/master)
- [PR/change to integrate it in
Neomake](https://github.com/neomake/neomake/pull/1600) (Neomake's test
setup is rather advanced, so do not let that scare you!)

## Links

- Discussion in Coverage.py's issue tracker:
[coverage issue 607](https://bitbucket.org/ned/coveragepy/issues/607/)

## TODO

- Line hit counts: known to covimerage, but not supported by Coverage.py
(<https://bitbucket.org/ned/coveragepy/issues/607/#comment-40048034>).
Loading

0 comments on commit 1e94207

Please sign in to comment.