Compare commits

...

68 commits

Author SHA1 Message Date
Camilo Nova
5a8531f82f
Merge pull request #31 from jazzband/jazzband/sync/default
Jazzband: Synced file(s) with jazzband/.github
2021-10-21 14:26:15 -05:00
jazzband-bot
0ddc447852 Jazzband: Created local 'CODE_OF_CONDUCT.md' from remote 'CODE_OF_CONDUCT.md' 2021-10-21 14:34:50 +00:00
Jannis Leidel
a1d5b7a844
Merge pull request #30 from jazzband/master-to-main
Rename Django's dev branch to main.
2021-03-09 13:33:58 +01:00
Jannis Leidel
9fcf06e85d
Rename Django's dev branch to main.
More information: https://groups.google.com/g/django-developers/c/tctDuKUGosc/
Refs: https://github.com/django/django/pull/14048
2021-03-09 13:33:38 +01:00
Camilo Nova
c0c859dfdd Merge pull request #29 from theatlantic/coverage-get-data
Add support for coverage 4.0.
2016-07-21 17:40:01 -05:00
Chris Barna
a858d0ab5a Add support for coverage 4.0.
* coverage._harvest_data() was renamed to coverage.get_data()
2016-07-21 15:05:08 -04:00
Camilo Nova
5037a98c1c Merge pull request #28 from adamchainz/readthedocs.io
Convert readthedocs links for their .org -> .io migration for hosted projects
2016-06-11 09:43:17 -05:00
Adam Chainz
03cb91ee03 Convert readthedocs links for their .org -> .io migration for hosted projects
As per [their blog post of the 27th April](https://blog.readthedocs.com/securing-subdomains/) ‘Securing subdomains’:

> Starting today, Read the Docs will start hosting projects from subdomains on the domain readthedocs.io, instead of on readthedocs.org. This change addresses some security concerns around site cookies while hosting user generated data on the same domain as our dashboard.

Test Plan: Manually visited all the links I’ve modified.
2016-06-11 10:58:46 +01:00
Simon Charette
ac32a48c60 Made CI install a version of virtualenv compatible with Python 3.2. 2016-02-03 22:07:09 -05:00
Simon Charette
f72e23da19 Merge pull request #26 from pinnokio/fix_dump_xml_in_results
Fix total_seconds invocation in dump_xml
2016-02-03 22:04:02 -05:00
Konstantin Lazarenko
61345906c7 Fix total_seconds invocation in dump_xml 2016-02-03 16:52:20 +02:00
Simon Charette
960dcfc1ad Updated the package classifiers. 2016-01-08 23:52:06 -05:00
Simon Charette
3376c56170 Added the TravisCI badge to the README. 2016-01-08 23:49:56 -05:00
Simon Charette
67829eb216 Added isort to CI. 2016-01-08 23:29:22 -05:00
Simon Charette
ea2b0d4464 Only install mock on version of Python not shipping it. 2016-01-08 23:16:19 -05:00
Simon Charette
05cc5c03b0 Added flake8 to CI. 2016-01-08 23:13:34 -05:00
Simon Charette
0842090e22 Adjusted TOX requirements on Python 3.2. 2016-01-08 22:59:33 -05:00
Simon Charette
8ac8db8d52 Removed support code for Django < 1.7. 2016-01-08 22:59:33 -05:00
Simon Charette
060a4344de Removed an unecessary requirements file. 2016-01-08 22:59:33 -05:00
Simon Charette
18796e1d78 Removed unused support code for Python 2.6. 2016-01-08 22:59:33 -05:00
Camilo Nova
3f37a73437 Merge pull request #24 from charettes/ci
Added CI
2016-01-08 08:47:39 -05:00
Simon Charette
65dbdd83c6 Added a TravisCI configuration file. 2016-01-08 01:58:49 -05:00
Simon Charette
cc6b2315f5 Made the required changes to make the tests pass on all supported Django versions. 2016-01-08 01:58:49 -05:00
Simon Charette
f0786c590b Added a TOX configuration to run CI against all supported Django versions. 2016-01-08 01:41:51 -05:00
Camilo Nova
b0757dc508 Update and rename README.rst to README.md 2016-01-07 16:38:32 -05:00
Camilo Nova
fab998bed3 Create CONTRIBUTING.md 2016-01-07 16:35:42 -05:00
Camilo Nova
a006230dcd Update README.rst 2016-01-07 11:57:39 -05:00
Camilo Nova
16016e8ac9 Update and rename README.md to README.rst 2016-01-07 11:56:35 -05:00
Camilo Nova
43443d0afc Added to jazzband 2016-01-07 11:54:48 -05:00
Camilo Nova
caab2ba679 Improved release docs 2016-01-07 08:16:39 -05:00
Camilo Nova
85583fe7ff Release 0.1.4 2016-01-07 08:13:37 -05:00
Camilo Nova
9495bd9fe6 Merge pull request #22 from theatlantic/django-18-compat
Make compatible with Django 1.8
2016-01-06 17:06:52 -05:00
Frankie Dintino
9f88b9f1fa Make compatible with Django 1.8
In Django 1.8, DiscoverRunner.option_list is replaced with the classmethod
DiscoverRunner.add_arguments()
2015-08-19 16:20:50 -04:00
Camilo Nova
3202fc742b Added developer instructions 2015-01-22 16:33:50 -05:00
Camilo Nova
ca92e0e175 Bump version 2015-01-22 16:04:42 -05:00
Camilo Nova
2ef826fb64 Improve documentation 2015-01-22 16:03:55 -05:00
Camilo Nova
9bb8198332 Remove unused import 2015-01-21 17:52:30 -05:00
Camilo Nova
4f5a005a31 Tweaks 2015-01-21 17:43:30 -05:00
Camilo Nova
84b81f7158 Merge pull request #20 from AxiaCore/master
Make coverage works and exclude files. Fixes #19
2015-01-21 16:49:27 -05:00
Camilo Nova
9d6f93ac9a Merge pull request #17 from arthur-debert/ascii-blowup-results
Fixed result when failure message has non ascii text
2015-01-21 16:47:55 -05:00
Peter Baumgartner
fc17c086e2 Removes deprecated option from Pylint
Fixes #9
`parseable` was deprecated with the release of Pylint 1.0 http://www.logilab.org/163292
2014-06-17 22:07:23 -05:00
Peter Baumgartner
ca843af43b Merge pull request #18 from arthur-debert/pip-install-doc
Fixed typo in project's PyPI name
2014-06-17 21:54:34 -05:00
Arthur Debert
ca2c616f1c Fixed typo in project's Pipy name 2014-01-02 22:24:24 -02:00
Arthur Debert
be173e4309 Fixed result when failure message has non ascii text 2014-01-02 22:18:28 -02:00
Camilo Nova
18b35ffdca Make coverage works and exclude files 2013-12-06 12:35:51 -05:00
bkonkle
d074b54b57 Increment version 2013-11-22 10:01:09 -06:00
Brandon Konkle
26b6dd84fe Add the pylint.rc to the MANIFEST.in 2013-11-22 09:59:52 -06:00
Brandon Konkle
56256a9265 Add @coagulant to authors 2013-11-22 09:57:07 -06:00
bkonkle
e3bb630bbd Minor style tweak 2013-11-22 09:55:18 -06:00
bkonkle
162cbc58d0 Merge branch 'flake8' of git://github.com/coagulant/django-discover-jenkins into coagulant-flake8 2013-11-22 09:50:21 -06:00
Brandon Konkle
bad63db403 Merge pull request #11 from camilonova/patch-2
Set relative path instead of absolute for files
2013-11-22 07:47:29 -08:00
coagulant
8fbc08d119 Add flake8 support
Flake8 is PEP8 + PyFlakes + Cyclomatic complexity check
2013-11-19 22:59:09 +04:00
Camilo Nova
7a2d660c73 Set relative path instead of absolute for files
Jenkins violations plugin requires the relative path in order to properly link the file when looking at violations report
2013-11-07 15:07:29 -05:00
Brandon Konkle
34605716ee Merge pull request #8 from camilonova/patch-1
fix typo
2013-10-07 07:53:47 -07:00
Camilo Nova
e8ffce4d4c fix typo 2013-10-07 08:45:57 -05:00
Brandon Konkle
dbbebfa1b1 Fix the crate.io link 2013-10-04 13:24:54 -05:00
Brandon Konkle
c8ae2a491d Add a version number badge, because badges are win! 2013-10-04 13:23:22 -05:00
Brandon Konkle
b1781a6f39 Bump version number and add authors 2013-10-03 09:40:09 -05:00
Brandon Konkle
08b424ebfd Merge pull request #7 from fxdgear/master
fixing default TEST_TASKS to match paths
2013-10-03 07:34:37 -07:00
Nick Lang
5197fe8080 fixing default TEST_TASKS to match paths 2013-10-02 15:13:18 -06:00
Brandon Konkle
95d1c336f8 Fix my links 2013-09-05 10:46:34 -05:00
Brandon Konkle
0e9379700c Add PyPi downloads 2013-09-05 10:45:37 -05:00
Brandon Konkle
e05ad02ee8 Merge pull request #5 from nvbn/master
pep8 task and tasks paths in docs
2013-09-03 12:02:55 -07:00
nvbn
12f3e707f6 Add pep8 task 2013-09-01 09:01:42 +04:00
nvbn
31e8e2059c Fix paths in docs 2013-09-01 08:48:13 +04:00
Brandon Konkle
38d30b395b Merge pull request #4 from jefftriplett/patch-1
Update settings.rst
2013-08-20 14:32:16 -07:00
Jeff Triplett
ba16ef57d1 Update settings.rst
Updated TEST_TASKS to reflect renamed task files.
2013-08-20 11:31:31 -05:00
Brandon Konkle
bcdf2475e6 Correct the package name 2013-08-08 02:00:52 -05:00
30 changed files with 694 additions and 293 deletions

38
.travis.yml Normal file
View file

@ -0,0 +1,38 @@
sudo: no
language: python
env:
- TOXENV=flake8
- TOXENV=isort
- TOXENV=py27-1.7
- TOXENV=py27-1.8
- TOXENV=py27-1.9
- TOXENV=py27-main
- TOXENV=py32-1.7
- TOXENV=py32-1.8
- TOXENV=py33-1.7
- TOXENV=py33-1.8
- TOXENV=py34-1.7
- TOXENV=py34-1.8
- TOXENV=py34-1.9
- TOXENV=py34-main
matrix:
include:
- python: 3.5
env: TOXENV=py35-1.8
- python: 3.5
env: TOXENV=py35-1.9
- python: 3.5
env: TOXENV=py35-main
allow_failures:
- env: TOXENV=py27-main
- env: TOXENV=py34-main
- env: TOXENV=py35-main
install:
- pip install tox "virtualenv<14.0"
script:
- tox

View file

@ -2,6 +2,11 @@ Authors
=======
* Brandon Konkle (https://github.com/bkonkle)
* Camilo Nova (https://github.com/camilonova)
* Jeff Triplett (https://github.com/jefftriplett)
* Vladimir Iakovlev (https://github.com/nvbn)
* Nick Lang (https://github.com/fxdgear)
* Ilya Baryshev (https://github.com/coagulant)
This project is a fork of the django-jenkins project. It would not be possible without the effort of Mikhail Podgurskiy and the django-jenkins project contributors. Thank you!

46
CODE_OF_CONDUCT.md Normal file
View file

@ -0,0 +1,46 @@
# Code of Conduct
As contributors and maintainers of the Jazzband projects, and in the interest of
fostering an open and welcoming community, we pledge to respect all people who
contribute through reporting issues, posting feature requests, updating documentation,
submitting pull requests or patches, and other activities.
We are committed to making participation in the Jazzband a harassment-free experience
for everyone, regardless of the level of experience, gender, gender identity and
expression, sexual orientation, disability, personal appearance, body size, race,
ethnicity, age, religion, or nationality.
Examples of unacceptable behavior by participants include:
- The use of sexualized language or imagery
- Personal attacks
- Trolling or insulting/derogatory comments
- Public or private harassment
- Publishing other's private information, such as physical or electronic addresses,
without explicit permission
- Other unethical or unprofessional conduct
The Jazzband roadies have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are not
aligned to this Code of Conduct, or to ban temporarily or permanently any contributor
for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
By adopting this Code of Conduct, the roadies commit themselves to fairly and
consistently applying these principles to every aspect of managing the jazzband
projects. Roadies who do not follow or enforce the Code of Conduct may be permanently
removed from the Jazzband roadies.
This code of conduct applies both within project spaces and in public spaces when an
individual is representing the project or its community.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by
contacting the roadies at `roadies@jazzband.co`. All complaints will be reviewed and
investigated and will result in a response that is deemed necessary and appropriate to
the circumstances. Roadies are obligated to maintain confidentiality with regard to the
reporter of an incident.
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version
1.3.0, available at [https://contributor-covenant.org/version/1/3/0/][version]
[homepage]: https://contributor-covenant.org
[version]: https://contributor-covenant.org/version/1/3/0/

3
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,3 @@
[![Jazzband](https://jazzband.co/static/img/jazzband.svg)](https://jazzband.co/)
This is a [Jazzband](https://jazzband.co/) project. By contributing you agree to abide by the [Contributor Code of Conduct](https://jazzband.co/docs/conduct) and follow the [guidelines](https://jazzband.co/docs/guidelines).

19
DEVEL.md Normal file
View file

@ -0,0 +1,19 @@
Developer instructions
======================
Here you can find some instructions when developing for this package.
Release a new version
---------------------
When you are ready to release a new version you need to follow these steps.
For example version 1.0.3:
1. Change the version number at ```discover_jenkins/__init__.py```
2. Commit ```git commit -m "Release 1.0.3"```
3. Tag ```git tag 1.0.3```
4. Push changes ```git push origin master```
5. Push tags ```git push --tags```
6. Upload release to Pypi ```python setup.py sdist upload```
7. Dance!

View file

@ -1 +1 @@
include *.md LICENSE
include *.md LICENSE discover_jenkins/tasks/pylint.rc

View file

@ -1,18 +1,20 @@
django-discover-jenkins
=======================
[![Build Status](https://drone.io/github.com/lincolnloop/django-discover-jenkins/status.png)](https://drone.io/github.com/lincolnloop/django-discover-jenkins/latest)
[![Build Status](https://travis-ci.org/jazzband/django-discover-jenkins.svg?branch=master)](https://travis-ci.org/jazzband/django-discover-jenkins)
[![Jazzband](https://jazzband.co/static/img/badge.svg)](https://jazzband.co/)
A streamlined fork of django-jenkins designed to work with the default test command and the discover runner.
[Read the Docs](https://django-discover-jenkins.readthedocs.org/)
[Read the Docs](https://django-discover-jenkins.readthedocs.io/)
Why?
----
The overall goal is to run tests on Jenkins the same way you do on your local machine. This project is designed to take advantage of [django-discover-runner](https://github.com/jezdez/django-discover-runner/), which is the default test runner in Django 1.6. Instead of using a setting to list which apps should be tested, or accepting Django-specific test labels, it uses the official test discovery feature of the new unittest2.
The overall goal is to run tests on Jenkins the same way you do on your local machine. This project is designed to take advantage of https://github.com/jezdez/django-discover-runner/, which is the default test runner in Django 1.6. Instead of using a setting to list which apps should be tested, or accepting Django-specific test labels, it uses the official test discovery feature of the new unittest2.
Also, the original [django-jenkins](https://github.com/kmmbvnr/django-jenkins) project doesn't take advantage of improvements to testing introduced in Django 1.4. Special management commands are no longer needed, as test runners themselves can add options that are handled by the built-in `test` command.
Also, the original https://github.com/kmmbvnr/django-jenkins project doesn't take advantage of improvements to testing introduced in Django 1.4. Special management commands are no longer needed, as test runners themselves can add options that are handled by the built-in `test` command.
What's Changed?
@ -22,10 +24,3 @@ What's Changed?
* **No management commands are provided.** Since Django 1.4, the built in 'test' command has allowed the test runner to define additional options that the management command will accept.
* **It doesn't use signals.** Instead of using the event/callback style of signals and using `inspect.getmembers` to connect everything, the test runner simply checks for key methods on each task the same way Django's request handler checks for methods on middleware.
* **Not everything works yet.** Only a subset of the django-jenkins tasks have been ported at this point. I'd love to accept your pull requests to add more of them.
Who?
----
First and foremost, the authors of [django-jenkins](https://github.com/kmmbvnr/django-jenkins) are responsible for the basis of most of this code. I ([Brandon Konkle](https://github.com/bkonkle)) just took it apart and put it back together again in a different way, then fixed or reworked some things. Thank you to the contributors of that project!
For the full list of original authors and for the contributors to this project, see the AUTHORS.md file.

View file

@ -1,3 +1,3 @@
__author__ = 'Brandon Konkle'
__version__ = '0.1.0'
__version__ = '0.1.4'

View file

@ -2,15 +2,11 @@ import os
import traceback
from datetime import datetime
from itertools import groupby
from unittest import TextTestResult
from xml.sax.saxutils import XMLGenerator
from xml.sax.xmlreader import AttributesImpl
from django.utils.unittest import TextTestResult
from discover_jenkins.utils import total_seconds
try:
from django.utils.encoding import smart_text
except ImportError:
from django.utils.encoding import smart_unicode as smart_text
from django.utils.encoding import smart_text
STDOUT_LINE = '\nStdout:\n%s'
STDERR_LINE = '\nStderr:\n%s'
@ -176,9 +172,9 @@ class XMLTestResult(TextTestResult):
document.startDocument()
document.startElement('testsuites', AttributesImpl({}))
suites = groupby(self.testInfos,
key=lambda test_info: self.test_case_name(
test_info.test_method))
suites = groupby(
self.testInfos, key=lambda test_info: self.test_case_name(test_info.test_method)
)
for suite_name, suite in suites:
document.startElement('testsuite',
AttributesImpl({'name': suite_name}))
@ -187,26 +183,26 @@ class XMLTestResult(TextTestResult):
document.startElement('testcase', AttributesImpl({
'classname': suite_name,
'name': self.test_method_name(test_info.test_method),
'time': '%3f' % total_seconds(
test_info.end_time - test_info.start_time)
'time': '%3f' % (
test_info.end_time - test_info.start_time
).total_seconds()
}))
if test_info.result == TestInfo.RESULT.ERROR:
document.startElement('error', AttributesImpl({
'message': smart_text(test_info.err[1])
}))
document.characters(self._exc_info_to_string(
test_info.err, test_info.test_method))
document.characters(self._exc_info_to_string(test_info.err, test_info.test_method))
document.endElement('error')
elif test_info.result == TestInfo.RESULT.FAILURE:
document.startElement('failure', AttributesImpl({
'message': smart_text(test_info.err[1])
}))
document.characters(self._exc_info_to_string(
test_info.err, test_info.test_method))
document.characters(
self._exc_info_to_string(test_info.err, test_info.test_method).decode('utf-8')
)
document.endElement('failure')
elif test_info.result == \
TestInfo.RESULT.UNEXPECTED_SUCCESS:
elif test_info.result == TestInfo.RESULT.UNEXPECTED_SUCCESS:
document.startElement('error', AttributesImpl({
'message': 'Unexpected success'
}))

View file

@ -1,20 +1,13 @@
import inspect
import unittest
from importlib import import_module
from optparse import make_option
import django
from django.core.exceptions import ImproperlyConfigured
from django.utils import unittest
from django.utils.importlib import import_module
try:
# Django 1.6
from django.test.runner import DiscoverRunner
except ImportError:
# Fallback to third-party app on Django 1.5
from discover_runner.runner import DiscoverRunner
from django.test.runner import DiscoverRunner
from .results import XMLTestResult
from .settings import TASKS, OUTPUT_DIR
from .settings import OUTPUT_DIR, TASKS
def get_tasks():
@ -55,22 +48,23 @@ class CIRunner(object):
A Django test runner mixin that runs tasks for Jenkins and dumps the
results to an XML file.
"""
option_list = get_task_options() + (
make_option(
'--jenkins',
action='store_true',
dest='jenkins',
default=False,
help='Process the Jenkins tasks from TEST_JENKINS_TASKS.'
),
make_option(
'--output-dir',
action='store',
dest='output_dir',
default=OUTPUT_DIR,
help='Top level of project for unittest discovery.'
),
)
if django.VERSION < (1, 8):
option_list = get_task_options() + (
make_option(
'--jenkins',
action='store_true',
dest='jenkins',
default=False,
help='Process the Jenkins tasks from TEST_JENKINS_TASKS.'
),
make_option(
'--output-dir',
action='store',
dest='output_dir',
default=OUTPUT_DIR,
help='Top level of project for unittest discovery.'
),
)
def __init__(self, jenkins=False, output_dir=None, **options):
super(CIRunner, self).__init__(**options)
@ -88,6 +82,20 @@ class CIRunner(object):
instance = task_class(output_dir=output_dir, **options)
self.tasks.append(instance)
@classmethod
def add_arguments(cls, parser):
task_classes = get_tasks()
for task_cls in task_classes:
if hasattr(task_cls, 'add_arguments'):
task_cls.add_arguments(parser)
parser.add_argument('--jenkins',
action='store_true', dest='jenkins', default=False,
help='Process the Jenkins tasks from TEST_JENKINS_TASKS.')
parser.add_argument('--output-dir',
action='store', dest='output_dir', default=OUTPUT_DIR,
help='Top level of project for unittest discovery.')
def setup_test_environment(self, **kwargs):
super(CIRunner, self).setup_test_environment(**kwargs)
if self.jenkins:
@ -130,4 +138,11 @@ class CIRunner(object):
class DiscoverCIRunner(CIRunner, DiscoverRunner):
"""The CIRunner mixin applied to the discover runner"""
option_list = DiscoverRunner.option_list + CIRunner.option_list
if django.VERSION < (1, 8):
option_list = DiscoverRunner.option_list + CIRunner.option_list
@classmethod
def add_arguments(cls, parser):
DiscoverRunner.add_arguments(parser)
CIRunner.add_arguments(parser)

View file

@ -1,9 +1,8 @@
from django.conf import settings
TASKS = getattr(settings, 'TEST_TASKS', (
'discover_jenkins.tasks.pylint.PyLintTask',
'discover_jenkins.tasks.coverage.CoverageTask',
'discover_jenkins.tasks.run_pylint.PyLintTask',
'discover_jenkins.tasks.with_coverage.CoverageTask',
))
OUTPUT_DIR = getattr(settings, 'TEST_OUTPUT_DIR', 'reports')
PYLINT_RCFILE = getattr(settings, 'TEST_PYLINT_RCFILE', 'pylint.rc')
@ -12,8 +11,7 @@ PROJECT_APPS = getattr(settings, 'TEST_PROJECT_APPS', ())
COVERAGE_WITH_MIGRATIONS = getattr(settings, 'TEST_COVERAGE_WITH_MIGRATIONS', False)
COVERAGE_REPORT_HTML_DIR = getattr(settings, 'TEST_COVERAGE_REPORT_HTML_DIR', '')
COVERAGE_MEASURE_BRANCH = getattr(settings, 'TEST_COVERAGE_MEASURE_BRANCH', True)
COVERAGE_EXCLUDES = getattr(settings, 'TEST_COVERAGE_EXCLUDES', [])
COVERAGE_EXCLUDES_FOLDERS = getattr(settings, 'TEST_COVERAGE_EXCLUDES_FOLDERS', [])
COVERAGE_EXCLUDE_PATHS = getattr(settings, 'TEST_COVERAGE_EXCLUDE_PATHS', [])
COVERAGE_RCFILE = getattr(settings, 'TEST_COVERAGE_RCFILE', 'coverage.rc')
JSHINT_CHECKED_FILES = getattr(settings, 'TEST_JSHINT_CHECKED_FILES', None)

View file

@ -5,7 +5,7 @@ ignore=migrations
cache-size=500
[MESSAGES CONTROL]
# C0111 Missing docstring
# C0111 Missing docstring
# I0011 Warning locally suppressed using disable-msg
# I0012 Warning locally suppressed using disable-msg
# W0704 Except doesn't do anything Used when an except clause does nothing but "pass" and there is no "else" clause
@ -18,9 +18,7 @@ cache-size=500
disable=C0111,I0011,I0012,W0704,W0142,W0212,W0232,W0613,W0702,R0201
[REPORTS]
output-format=parseable
include-ids=yes
msg-template={path}:{line}: [{msg_id}({symbol}), {obj}] {msg}
[BASIC]
no-docstring-rgx=__.*__|_.*
@ -31,7 +29,6 @@ const-rgx=(([A-Z_][A-Z0-9_]*)|([a-z_][a-z0-9_]*)|(__.*__)|register|urlpatterns)$
good-names=_,i,j,k,e,qs,pk,setUp,tearDown
[TYPECHECK]
# Tells whether missing members accessed in mixin class should be ignored. A
# mixin class is detected if its name ends with "mixin" (case insensitive).
ignore-mixin-members=yes
@ -51,7 +48,6 @@ generated-members=objects,DoesNotExist,id,pk,_meta,base_fields,context
# List of method names used to declare (i.e. assign) instance attributes
defining-attr-methods=__init__,__new__,setUp
[VARIABLES]
init-import=no
dummy-variables-rgx=_|dummy
@ -61,17 +57,14 @@ min-similarity-lines=6
ignore-comments=yes
ignore-docstrings=yes
[MISCELLANEOUS]
notes=FIXME,XXX,TODO
[FORMAT]
max-line-length=160
max-module-lines=500
indent-string=' '
[DESIGN]
max-args=10
max-locals=15
@ -82,4 +75,3 @@ max-parents=7
max-attributes=7
min-public-methods=0
max-public-methods=50

View file

@ -0,0 +1,72 @@
# coding: utf-8
import os
import sys
from optparse import make_option
import django
import pep8
from flake8.engine import get_style_guide
from ..utils import get_app_locations
from .run_pep8 import Pep8Task
class Flake8Task(Pep8Task):
if django.VERSION < (1, 8):
option_list = Pep8Task.option_list + (
make_option(
'--max-complexity',
dest='max_complexity',
help='McCabe complexity threshold',
),
)
def __init__(self, **options):
super(Flake8Task, self).__init__(**options)
if options.get('flake8_file_output', True):
output_dir = options['output_dir']
if not os.path.exists(output_dir):
os.makedirs(output_dir)
self.output = open(os.path.join(output_dir, 'flake8.report'), 'w')
else:
self.output = sys.stdout
if options['max_complexity']:
self.pep8_options['max_complexity'] = int(options['max_complexity'])
@classmethod
def add_arguments(cls, parser):
Pep8Task.add_arguments(parser)
parser.add_argument('--max-complexity',
dest='max_complexity',
help='McCabe complexity threshold')
def teardown_test_environment(self, **kwargs):
class JenkinsReport(pep8.BaseReport):
def error(instance, line_number, offset, text, check):
code = super(JenkinsReport, instance).error(
line_number, offset, text, check,
)
if not code:
return
sourceline = instance.line_offset + line_number
self.output.write(
'%s:%s:%s: %s\n' %
(instance.filename, sourceline, offset + 1, text),
)
flake8style = get_style_guide(
parse_argv=False,
config_file=self.pep8_rcfile,
reporter=JenkinsReport,
**self.pep8_options)
# Jenkins pep8 validator requires relative paths
project_root = os.path.abspath(os.path.dirname(__name__))
for location in map(lambda x: os.path.relpath(x, project_root), get_app_locations()):
flake8style.input_dir(location)
self.output.close()

View file

@ -1,53 +1,56 @@
# -*- coding: utf-8 -*-
import os
import sys
import codecs
import fnmatch
import os
import subprocess
import sys
from optparse import make_option
import django
from django.conf import settings as django_settings
from ..settings import JSHINT_CHECKED_FILES, JSHINT_EXCLUDE, JSHINT_RCFILE
from ..utils import CalledProcessError, get_app_locations
from ..settings import JSHINT_CHECKED_FILES, JSHINT_RCFILE, JSHINT_EXCLUDE
class JSHintTask(object):
option_list = (
make_option(
"--jshint-no-staticdirs",
dest="jshint-no-staticdirs",
default=False,
action="store_true",
help="Don't check js files located in STATICFILES_DIRS settings"
),
make_option(
"--jshint-with-minjs",
dest="jshint_with-minjs",
default=False,
action="store_true",
help="Do not ignore .min.js files"
),
make_option(
"--jshint-exclude",
dest="jshint_exclude",
default=JSHINT_EXCLUDE,
help="Exclude patterns"
),
make_option(
'--jshint-stdout',
action='store_true',
dest='jshint_stdout',
default=False,
help='Print the jshint output instead of storing it in a file'
),
make_option(
'--jshint-rcfile',
dest='jshint_rcfile',
default=JSHINT_RCFILE,
help='Provide an rcfile for jshint'
),
)
if django.VERSION < (1, 8):
option_list = (
make_option(
"--jshint-no-staticdirs",
dest="jshint-no-staticdirs",
default=False,
action="store_true",
help="Don't check js files located in STATICFILES_DIRS settings"
),
make_option(
"--jshint-with-minjs",
dest="jshint_with-minjs",
default=False,
action="store_true",
help="Do not ignore .min.js files"
),
make_option(
"--jshint-exclude",
dest="jshint_exclude",
default=JSHINT_EXCLUDE,
help="Exclude patterns"
),
make_option(
'--jshint-stdout',
action='store_true',
dest='jshint_stdout',
default=False,
help='Print the jshint output instead of storing it in a file'
),
make_option(
'--jshint-rcfile',
dest='jshint_rcfile',
default=JSHINT_RCFILE,
help='Provide an rcfile for jshint'
),
)
def __init__(self, **options):
self.to_stdout = options['jshint_stdout']
@ -68,6 +71,24 @@ class JSHintTask(object):
if isinstance(self.exclude, str):
self.exclude = self.exclude.split(',')
@classmethod
def add_arguments(cls, parser):
parser.add_argument("--jshint-no-staticdirs",
dest="jshint-no-staticdirs", default=False, action="store_true",
help="Don't check js files located in STATICFILES_DIRS settings")
parser.add_argument("--jshint-with-minjs",
dest="jshint_with-minjs", default=False, action="store_true",
help="Do not ignore .min.js files")
parser.add_argument("--jshint-exclude",
dest="jshint_exclude", default=JSHINT_EXCLUDE,
help="Exclude patterns")
parser.add_argument('--jshint-stdout',
action='store_true', dest='jshint_stdout', default=False,
help='Print the jshint output instead of storing it in a file')
parser.add_argument('--jshint-rcfile',
dest='jshint_rcfile', default=JSHINT_RCFILE,
help='Provide an rcfile for jshint')
def teardown_test_environment(self, **kwargs):
files = [path for path in self.static_files_iterator()]

View file

@ -0,0 +1,112 @@
# -*- coding: utf-8 -*-
import os
import sys
from optparse import make_option
import django
import pep8
from django.conf import settings
from ..utils import get_app_locations
class Pep8Task(object):
if django.VERSION < (1, 8):
option_list = (
make_option(
"--pep8-exclude",
dest="pep8-exclude",
default=pep8.DEFAULT_EXCLUDE + ",migrations",
help="exclude files or directories which match these "
"comma separated patterns (default: %s)" %
pep8.DEFAULT_EXCLUDE
),
make_option(
"--pep8-select", dest="pep8-select",
help="select errors and warnings (e.g. E,W6)",
),
make_option(
"--pep8-ignore", dest="pep8-ignore",
help="skip errors and warnings (e.g. E4,W)",
),
make_option(
"--pep8-max-line-length",
dest="pep8-max-line-length", type='int',
help="set maximum allowed line length (default: %d)" %
pep8.MAX_LINE_LENGTH
),
make_option(
"--pep8-rcfile", dest="pep8-rcfile",
help="PEP8 configuration file"
),
)
def __init__(self, **options):
if options.get('pep8_file_output', True):
output_dir = options['output_dir']
if not os.path.exists(output_dir):
os.makedirs(output_dir)
self.output = open(os.path.join(output_dir, 'pep8.report'), 'w')
else:
self.output = sys.stdout
self.pep8_rcfile = options['pep8-rcfile'] or self.default_config_path()
self.pep8_options = {'exclude': options['pep8-exclude'].split(',')}
if options['pep8-select']:
self.pep8_options['select'] = options['pep8-select'].split(',')
if options['pep8-ignore']:
self.pep8_options['ignore'] = options['pep8-ignore'].split(',')
if options['pep8-max-line-length']:
self.pep8_options['max_line_length'] = options['pep8-max-line-length']
@classmethod
def add_arguments(cls, parser):
parser.add_argument("--pep8-exclude",
dest="pep8-exclude",
default=pep8.DEFAULT_EXCLUDE + ",migrations",
help="exclude files or directories which match these "
"comma separated patterns (default: %s)" %
pep8.DEFAULT_EXCLUDE)
parser.add_argument("--pep8-select", dest="pep8-select",
help="select errors and warnings (e.g. E,W6)")
parser.add_argument("--pep8-ignore", dest="pep8-ignore",
help="skip errors and warnings (e.g. E4,W)")
parser.add_argument("--pep8-max-line-length",
dest="pep8-max-line-length", type=int,
help="set maximum allowed line length (default: %d)" %
pep8.MAX_LINE_LENGTH)
parser.add_argument("--pep8-rcfile", dest="pep8-rcfile",
help="PEP8 configuration file")
def teardown_test_environment(self, **kwargs):
locations = get_app_locations()
class JenkinsReport(pep8.BaseReport):
def error(instance, line_number, offset, text, check):
code = super(JenkinsReport, instance).error(
line_number, offset, text, check,
)
if not code:
return
sourceline = instance.line_offset + line_number
self.output.write(
'%s:%s:%s: %s\n' %
(instance.filename, sourceline, offset + 1, text),
)
pep8style = pep8.StyleGuide(
parse_argv=False, config_file=self.pep8_rcfile,
reporter=JenkinsReport, **self.pep8_options
)
for location in locations:
pep8style.input_dir(os.path.relpath(location))
self.output.close()
@staticmethod
def default_config_path():
rcfile = getattr(settings, 'PEP8_RCFILE', 'pep8.rc')
return rcfile if os.path.exists(rcfile) else None

View file

@ -4,10 +4,11 @@ import os
import sys
from optparse import make_option
import django
from pylint import lint
from pylint.reporters.text import ParseableTextReporter
from ..settings import PYLINT_RCFILE, PROJECT_APPS
from ..settings import PROJECT_APPS, PYLINT_RCFILE
def default_config_path():
@ -21,21 +22,23 @@ def default_config_path():
class PyLintTask(object):
option_list = (
make_option(
"--pylint-rcfile",
dest="pylint_rcfile",
default=None,
help="pylint configuration file"
),
make_option(
"--pylint-errors-only",
dest="pylint_errors_only",
action="store_true",
default=False,
help="pylint output errors only mode"
),
)
if django.VERSION < (1, 8):
option_list = (
make_option(
"--pylint-rcfile",
dest="pylint_rcfile",
default=None,
help="pylint configuration file"
),
make_option(
"--pylint-errors-only",
dest="pylint_errors_only",
action="store_true",
default=False,
help="pylint output errors only mode"
),
)
def __init__(self, **options):
self.config_path = options['pylint_rcfile'] or default_config_path()
@ -49,6 +52,15 @@ class PyLintTask(object):
else:
self.output = sys.stdout
@classmethod
def add_arguments(cls, parser):
parser.add_argument("--pylint-rcfile",
dest="pylint_rcfile", default=None,
help="pylint configuration file")
parser.add_argument("--pylint-errors-only",
dest="pylint_errors_only", action="store_true", default=False,
help="pylint output errors only mode")
def teardown_test_environment(self, **kwargs):
if PROJECT_APPS:
args = ["--rcfile=%s" % self.config_path]
@ -56,5 +68,8 @@ class PyLintTask(object):
args += ['--errors-only']
args += PROJECT_APPS
lint.Run(args, reporter=ParseableTextReporter(output=self.output),
exit=False)
lint.Run(
args,
reporter=ParseableTextReporter(output=self.output),
exit=False
)

View file

@ -1,28 +1,33 @@
# -*- coding: utf-8 -*-
import os
import subprocess
import sys
from optparse import make_option
from discover_jenkins.utils import check_output, get_app_locations
import django
from ..utils import get_app_locations
class SlocCountTask(object):
option_list = (
make_option(
"--sloccount-with-migrations",
action="store_true",
default=False,
dest="sloccount_with_migrations",
help="Count migrations sloc."
),
make_option(
'--sloccount-stdout',
action='store_true',
dest='sloccount_stdout',
default=False,
help='Print the sloccount totals instead of saving them to a file'
),
)
if django.VERSION < (1, 8):
option_list = (
make_option(
"--sloccount-with-migrations",
action="store_true",
default=False,
dest="sloccount_with_migrations",
help="Count migrations sloc."
),
make_option(
'--sloccount-stdout',
action='store_true',
dest='sloccount_stdout',
default=False,
help='Print the sloccount totals instead of saving them to a file'
),
)
def __init__(self, **options):
self.with_migrations = options['sloccount_with_migrations']
@ -36,10 +41,19 @@ class SlocCountTask(object):
self.output = open(os.path.join(output_dir,
'sloccount.report'), 'w')
@classmethod
def add_arguments(cls, parser):
parser.add_argument("--sloccount-with-migrations",
action="store_true", default=False, dest="sloccount_with_migrations",
help="Count migrations sloc.")
parser.add_argument("--sloccount-stdout",
action="store_true", dest="sloccount_stdout", default=False,
help="Print the sloccount totals instead of saving them to a file")
def teardown_test_environment(self, **kwargs):
locations = get_app_locations()
report_output = check_output(
report_output = subprocess.check_output(
['sloccount', "--duplicates", "--wide", "--details"] + locations
)
report_output = report_output.decode('utf-8')

View file

@ -3,12 +3,15 @@
import os
from optparse import make_option
from django.utils.importlib import import_module
from coverage.control import coverage
import django
from .. import settings
try:
from coverage import coverage
except ImportError:
from coverage.control import coverage
def default_config_path():
rcfile = settings.COVERAGE_RCFILE
@ -18,42 +21,44 @@ def default_config_path():
class CoverageTask(object):
option_list = (
make_option(
"--coverage-rcfile",
dest="coverage_rcfile",
default="",
help="Specify configuration file."
),
make_option(
"--coverage-html-report",
dest="coverage_html_report_dir",
default=settings.COVERAGE_REPORT_HTML_DIR,
help="Directory to which HTML coverage report should be"
" written. If not specified, no report is generated."
),
make_option(
"--coverage-no-branch-measure",
action="store_false",
default=settings.COVERAGE_MEASURE_BRANCH,
dest="coverage_measure_branch",
help="Don't measure branch coverage."
),
make_option(
"--coverage-with-migrations",
action="store_true",
default=settings.COVERAGE_WITH_MIGRATIONS,
dest="coverage_with_migrations",
help="Don't measure migrations coverage."
),
make_option(
"--coverage-exclude",
action="append",
default=settings.COVERAGE_EXCLUDES,
dest="coverage_excludes",
help="Module name to exclude"
if django.VERSION < (1, 8):
option_list = (
make_option(
"--coverage-rcfile",
dest="coverage_rcfile",
default="",
help="Specify configuration file."
),
make_option(
"--coverage-html-report",
dest="coverage_html_report_dir",
default=settings.COVERAGE_REPORT_HTML_DIR,
help="Directory to which HTML coverage report should be"
" written. If not specified, no report is generated."
),
make_option(
"--coverage-no-branch-measure",
action="store_false",
default=settings.COVERAGE_MEASURE_BRANCH,
dest="coverage_measure_branch",
help="Don't measure branch coverage."
),
make_option(
"--coverage-with-migrations",
action="store_true",
default=settings.COVERAGE_WITH_MIGRATIONS,
dest="coverage_with_migrations",
help="Don't measure migrations coverage."
),
make_option(
"--coverage-exclude",
action="append",
default=settings.COVERAGE_EXCLUDE_PATHS,
dest="coverage_excludes",
help="Paths to be excluded from coverage"
)
)
)
def __init__(self, **options):
self.output_dir = options['output_dir']
@ -61,21 +66,7 @@ class CoverageTask(object):
self.html_dir = options['coverage_html_report_dir']
self.branch = options['coverage_measure_branch']
self.exclude_locations = []
modnames = options['coverage_excludes']
for modname in modnames:
try:
self.exclude_locations.append(
os.path.dirname(
import_module(modname).__file__
)
)
except ImportError:
pass
# Extra folders to exclude. Particularly useful to specify things like
# apps/company/migrations/*
self.exclude_locations.extend(settings.COVERAGE_EXCLUDES_FOLDERS)
self.exclude_locations = options['coverage_excludes'] or None
self.coverage = coverage(
branch=self.branch,
@ -84,29 +75,60 @@ class CoverageTask(object):
config_file=options.get('coverage_rcfile') or default_config_path()
)
@classmethod
def add_arguments(cls, parser):
parser.add_argument("--coverage-rcfile",
dest="coverage_rcfile", default="",
help="Specify configuration file.")
parser.add_argument("--coverage-html-report",
dest="coverage_html_report_dir", default=settings.COVERAGE_REPORT_HTML_DIR,
help="Directory to which HTML coverage report should be"
" written. If not specified, no report is generated.")
parser.add_argument("--coverage-no-branch-measure",
action="store_false", default=settings.COVERAGE_MEASURE_BRANCH,
dest="coverage_measure_branch",
help="Don't measure branch coverage.")
parser.add_argument("--coverage-with-migrations",
action="store_true", default=settings.COVERAGE_WITH_MIGRATIONS,
dest="coverage_with_migrations",
help="Don't measure migrations coverage.")
parser.add_argument("--coverage-exclude",
action="append", default=settings.COVERAGE_EXCLUDE_PATHS,
dest="coverage_excludes",
help="Paths to be excluded from coverage")
def setup_test_environment(self, **kwargs):
self.coverage.start()
def teardown_test_environment(self, **kwargs):
self.coverage.stop()
try:
self.coverage._harvest_data()
except AttributeError:
# coverage._harvest_data was renamed to coverage.get_data in
# coverage.py 4.0.
self.coverage.get_data()
morfs = [filename for filename in self.coverage.data.measured_files()
if self.want_file(filename)]
if not os.path.exists(self.output_dir):
os.makedirs(self.output_dir)
self.coverage.xml_report(morfs=morfs,
outfile=os.path.join(
self.output_dir, 'coverage.xml'))
self.coverage.xml_report(
morfs=morfs,
outfile=os.path.join(self.output_dir, 'coverage.xml')
)
if self.html_dir:
self.coverage.html_report(morfs=morfs, directory=self.html_dir)
self.coverage.html_report(
morfs=morfs,
directory=self.html_dir
)
def want_file(self, filename):
if not self.with_migrations and '/migrations/' in filename:
return False
for location in self.exclude_locations:
if filename.startswith(location):
return False
return True

View file

@ -1,7 +1,6 @@
import os.path
import subprocess
from django.utils.importlib import import_module
from importlib import import_module
from discover_jenkins.settings import PROJECT_APPS
@ -16,28 +15,6 @@ class CalledProcessError(subprocess.CalledProcessError):
% (self.cmd, self.returncode, self.output))
def check_output(*popenargs, **kwargs):
"""
Backport from Python2.7
"""
if getattr(subprocess, 'check_output', None) is None:
if 'stdout' in kwargs or 'stderr' in kwargs:
raise ValueError('stdout or stderr argument not allowed, '
'it will be overridden.')
process = subprocess.Popen(stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
*popenargs, **kwargs)
output, err = process.communicate()
retcode = process.poll()
if retcode:
cmd = kwargs.get("args")
if cmd is None:
cmd = popenargs[0]
raise CalledProcessError(retcode, cmd, output=output + '\n' + err)
return output
return subprocess.check_output(*popenargs, **kwargs)
def find_first_existing_executable(exe_list):
"""
Accepts list of [('executable_file_path', 'options')],
@ -55,15 +32,6 @@ def find_first_existing_executable(exe_list):
return filepath
def total_seconds(delta):
"""
Backport timedelta.total_seconds() from Python 2.7
"""
if getattr(delta, 'total_seconds', None) is None:
return delta.days * 86400.0 + delta.seconds + delta.microseconds * 1e-6
return delta.total_seconds()
def get_app_locations():
"""
Returns list of paths to tested apps

View file

@ -5,7 +5,11 @@ Installation
From PyPI::
pip install django-discover-runner
pip install django-discover-jenkins
Due to a bug in the coverage library you have to use this specific version::
pip install coverage==3.5
Configuration
-------------
@ -22,7 +26,7 @@ the ``DiscoverCIRunner`` that ``discover_jenkins`` provides::
TEST_RUNNER = 'discover_jenkins.runner.DiscoverCIRunner'
Even though ``discover_jenkins`` doesn't use app names to discover tests, it
does use them to handle tasks like coverahe and pylint. Add your desired apps
does use them to handle tasks like coverage and pylint. Add your desired apps
to setting called ``TEST_PROJECT_APPS``::
TEST_PROJECT_APPS = (

View file

@ -11,8 +11,8 @@ Settings
Default value::
TEST_TASKS = (
'discover_jenkins.tasks.pylint.PyLintTask',
'discover_jenkins.tasks.coverage.CoverageTask',
'discover_jenkins.tasks.run_pylint.PyLintTask',
'discover_jenkins.tasks.with_coverage.CoverageTask',
)
* ``TEST_OUTPUT_DIR``

View file

@ -7,7 +7,7 @@ Tasks
CoverageTask
============
``discover_runner.tasks.with_coverage.CoverageTask``
``discover_jenkins.tasks.with_coverage.CoverageTask``
Reports test coverage across your apps. Uses the ``TEST_PROJECT_APPS`` setting.
@ -39,25 +39,19 @@ Settings
TEST_COVERAGE_MEASURE_BRANCH = True
* ``TEST_COVERAGE_EXCLUDES``
* ``TEST_COVERAGE_EXCLUDE_PATHS``
Module names to exclude.
File paths to exclude. Can be myapp/admin.py or myapp/management/*
Default value::
TEST_COVERAGE_EXCLUDES = []
* ``TEST_COVERAGE_EXCLUDES_FOLDERS``
Extra folders to exclude.
Default value::
TEST_COVERAGE_EXCLUDES_FOLDERS = []
TEST_COVERAGE_EXCLUDE_PATHS = []
* ``TEST_COVERAGE_RCFILE``
Specify configuration file.
Specify configuration file. Please note if you set the ``TEST_COVERAGE_EXCLUDE_PATHS``
setting, coverage will ignore your coverage.rc file. So if you want to customize
coverage settings only use this file and not the other settings.
Default value::
@ -66,7 +60,7 @@ Settings
PyLintTask
==========
``discover_runner.tasks.run_pylint.PyLintTask``
``discover_jenkins.tasks.run_pylint.PyLintTask``
Runs pylint across your apps. Uses the ``TEST_PROJECT_APPS`` setting.
@ -84,7 +78,7 @@ Settings
JSHintTask
==========
``discover_runner.tasks.run_jshint.JSHintTask``
``discover_jenkins.tasks.run_jshint.JSHintTask``
Runs jshint across your apps. Uses the ``TEST_PROJECT_APPS`` setting.
@ -118,6 +112,20 @@ Settings
SlocCountTask
=============
``discover_runner.tasks.run_sloccount.SlocCountTask``
``discover_jenkins.tasks.run_sloccount.SlocCountTask``
Run sloccount across your apps. Uses the ``TEST_PROJECT_APPS`` setting.
Pep8Task
========
``discover_jenkins.tasks.run_pep8.Pep8Task``
Run pep8 across your apps. Uses the ``TEST_PROJECT_APPS`` setting.
Flake8Task
==========
``discover_jenkins.tasks.run_flake8.Flake8Task``
Run flake8 across your apps. Uses the ``TEST_PROJECT_APPS`` setting.

View file

@ -1,2 +1,13 @@
[flake8]
ignore = E123,E128,E402,W503,E731,W601
max-line-length = 119
exclude = docs,tests/test_project/test_app/migrations/*
[isort]
combine_as_imports=true
include_trailing_comma=true
multi_line_output=5
not_skip=__init__.py
[wheel]
universal = 1

View file

@ -31,7 +31,7 @@ if sys.argv[-1] == 'publish':
setup(
name='django-discover-runner',
name='django-discover-jenkins',
version=version,
description="A minimal fork of django-jenkins designed to work with the "
"discover runner, made with simplicity in mind",
@ -46,10 +46,19 @@ setup(
"Development Status :: 3 - Alpha",
"Environment :: Web Environment",
"Framework :: Django",
"Framework :: Django :: 1.7",
"Framework :: Django :: 1.8",
"Framework :: Django :: 1.9",
"License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",
"Programming Language :: JavaScript",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.2",
"Programming Language :: Python :: 3.3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Topic :: Internet :: WWW/HTTP",
"Topic :: Internet :: WWW/HTTP :: Dynamic Content",
"Topic :: Software Development :: Libraries :: Python Modules",

View file

@ -1,5 +0,0 @@
django>=1.5
pylint>=0.23
coverage>=3.4
mock>=1.0.1
django-discover-runner>=1.0

View file

@ -1,4 +1,5 @@
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
DEBUG = True
@ -32,6 +33,7 @@ TEST_RUNNER = 'discover_jenkins.runner.DiscoverCIRunner'
TEST_TASKS = (
'discover_jenkins.tasks.with_coverage.CoverageTask',
'discover_jenkins.tasks.run_pylint.PyLintTask',
'discover_jenkins.tasks.run_flake8.Flake8Task',
'discover_jenkins.tasks.run_jshint.JSHintTask',
'discover_jenkins.tasks.run_sloccount.SlocCountTask',
)
@ -46,9 +48,9 @@ LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
},
},
'loggers': {
@ -58,4 +60,4 @@ LOGGING = {
'propagate': True,
},
}
}
}

View file

@ -1,9 +1,5 @@
from south.v2 import SchemaMigration
from django.db import migrations
class Migration(SchemaMigration):
def forwards(self, orm):
a = 1 # pyflakes/pylint violation
pass
def backwards(self, orm):
pass
class Migration(migrations.Migration):
a = 1 # pyflakes/pylint violation

View file

@ -1,7 +1,13 @@
from mock import MagicMock, patch
from unittest import skipIf
import django
from discover_jenkins import runner, tasks
from django.test import TestCase
from discover_jenkins import runner, tasks
try:
from unittest.mock import MagicMock, patch
except ImportError:
from mock import MagicMock, patch
class FakeTestRunner(object):
@ -24,7 +30,6 @@ class Runner(runner.CIRunner, FakeTestRunner):
class TestCIRunner(TestCase):
def test_get_tasks(self):
"""
Make sure the correct tasks are imported based on the
@ -33,15 +38,17 @@ class TestCIRunner(TestCase):
self.assertEqual(runner.get_tasks(),
[tasks.with_coverage.CoverageTask,
tasks.run_pylint.PyLintTask,
tasks.run_flake8.Flake8Task,
tasks.run_jshint.JSHintTask,
tasks.run_sloccount.SlocCountTask])
@skipIf(django.VERSION >= (1, 8), "optparse is not used on Django 1.8+")
def test_get_task_options(self):
"""
For now, just do a simple test to make sure the right number of options
are gleaned from the tasks.
"""
self.assertEqual(len(runner.get_task_options()), 14)
self.assertEqual(len(runner.get_task_options()), 20)
def test_setup_test_environment(self):
"""
@ -72,4 +79,3 @@ class TestCIRunner(TestCase):
cirun.teardown_test_environment()
self.assertTrue(mock_task.teardown_test_environment.called)

View file

@ -1,21 +1,12 @@
import os
from datetime import timedelta
from django.test import TestCase
import discover_jenkins
import test_project
from django.test import TestCase
class TestUtils(TestCase):
def test_total_seconds(self):
"""
The total_seconds util should show that 5 minutes is 300 seconds.
"""
delta = timedelta(minutes=5)
self.assertEqual(discover_jenkins.utils.total_seconds(delta), 300)
def test_app_locations(self):
"""
The app locations should come from the test_project settings.

48
tox.ini Normal file
View file

@ -0,0 +1,48 @@
[tox]
args_are_paths = false
envlist =
flake8,
isort,
py27-{1.7,1.8,1.9,main},
py32-{1.7,1.8},
py33-{1.7,1.8},
py34-{1.7,1.8,1.9,main},
py35-{1.8,1.9,main}
[testenv]
basepython =
py27: python2.7
py32: python3.2
py33: python3.3
py34: python3.4
py35: python3.5
usedevelop = true
setenv =
PYTHONPATH=tests
commands =
{envbindir}/python -Wonce tests/manage.py test tests
deps =
py32: coverage>=3.4,<4.0
{py27,py33,py34,py35}: coverage>=4.0
flake8>=2.1.0
{py27,py32}: mock>=1.0.1
py32: astroid==1.2
py32: logilab-common==0.62
py32: pylint==1.3
{py27,py33,py34,py35}: pylint>=0.23
1.7: Django>=1.7,<1.8
1.8: Django>=1.8,<1.9
1.9: Django>=1.9,<1.10
main: https://github.com/django/django/archive/main.tar.gz
[testenv:flake8]
basepython = python2.7
commands =
flake8
[testenv:isort]
basepython = python2.7
commands =
isort --recursive --check-only --diff discover_jenkins tests
deps =
isort