Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Polytester is a simple, groovy multi-language test runner.
It makes it easy to run tests in your polygot projects. Run python, javascript, ruby, java, and more side by side. It abstracts away the pain and config and lets you just get get developing. Easily.
Polytester Just Works with any testing framework that runs in the shell (yo, that's pretty much everything on the planet), and ships with extra-smooth integration for lots of common frameworks including django, karma, protractor, and more. Polytester was built by Steven Skoczen.
pip install polytester
Create a tests.yml file. The following example shows django, protractor, and karma (jasmine) tests.
api:
command: python manage.py test
js:
command: karma start karma.conf.js
e2e:
command: protractor
Run polytester
$ polytester
Detecting...
✔ api detected as django tests.
✔ e2e detected as protractor tests.
✔ js detected as karma tests.
Running tests...
✔ api - 35 tests passed.
✔ e2e - 17 tests passed.
✔ js - 23 tests passed.
✔ All tests passed.
Note that the status code returned is correct, so you can just dump this on your CI service, and be done.
That's it. There is no step 3.
Here's the above - polytester installed, configured, and running in less than 30 seconds:
Any test framework that returns standard error codes will work out of the box. That's pretty much everything.
In addition, polytester progressively upgrades to extra-nice output for the frameworks it has parsers for. As of v1.0, the following parsers are built-in, and it's simple to write your own. More are very much welcome via PR, and as you can see below, writing them is easy!
But again, for extra clarity - if your test runner returns normal output codes, you can just drop it in and it'll work great.
Polytester will respond to pt
or polytester
. Both do the exact same thing.
There are a variety of options to make development simple.
polytester foo
or polytester foo,bar
just runs the test suite(s) specified.--autoreload
or --ci
watches all files specified in a watch_glob
, and immediately runs the relevant suite on file changes. Any running tests are killed.--wip
runs tests flagged as "work in progress" by running the wip_command
for all suites that specify it.--verbose
or -v
dumps all output to the shell. To prevent collisions, when run in this mode, test suites are run in serial, instead of the normal parallel execution.--parallel n m
only runs test chunk n
of m
, for parallel build test environments.--config foo.yml
specifies a different location for the config file. Default is tests.yml
If you want to get more out of polytester, there's more under the surface, including wip, autoreload, pass/fail counts, custom frameworks, and more.
Here's all the goodness.
Having your tests auto-run when files change is super-handy. With polytester, it's simple.
Specify a watch_glob
(and optionally a watch_dir
) in your tests.yml
python:
command: nosetests
watch_glob: "*.py"
watch_dir: api
Run with --autoreload
polytester --autoreload
Any time you change a file that matches the glob, polytester will immediately run the matching test suite. Any running tests for that suite will be immediately killed.
Notes:
watch_dir
is not specified, it defaults to the current directory.*.html;*.js;*.css
.--autoreload
will only run the tests that have a watch_glob
in their config. Which makes sense once you think about it, but might suprise you at first glance.Autoreload in action:
Being able to tag and run certain groups of tests becomes a huge develoment time-saver for larger codebases. Polytester makes it simple. Just specify a wip_command
, and run with --wip
.
Specify a wip_command
in your tests.yml
python:
command: nosetests
wip_command: nosetests -a wip
Run with --wip
polytester --wip
That's it!
If you're running on a ci platform with parallel builds, like CircleCI, the --parallel
option can save you some time.
Just set up your build config to use it, and pass in the appropriate shell variables.
For CircleCI, just set your circle.yml
to:
test:
override:
- polytester --parallel $CIRCLE_NODE_INDEX $CIRCLE_NODE_TOTAL:
parallel: true
And you're all set. Your test suites will split out automatically, according to the number of build containers you have.
If you're using the default test command for any supported frameworks, polytester just detects the right one, and you're on your way. However, if you're using a custom runner, or something a bit special, you can easily just specify which parser polytester should use.
Let's say for reasons too complex to explain, I have a custom wrapper around my nose script. No problem. In my tests.yml
, I just tell polytester to expect nose output.
python:
command: my_custom_nose_script.sh
parser: polytester.NoseParser
Now, when you run, you get this output:
$ polytester
Detecting...
✔ python specified as nose tests.
Running tests...
✔ python: 47 tests passed.
✔ All tests passed.
Here's the full list of built-in parsers:
DefaultParser
(Just listens to exit codes, no support for number of tests.)NoseParser
DjangoParser
KarmaParser
ProtractorParser
SaladParser
If you need a parser not in this list, you can make it by writing a few simple functions. See Custom parsers below.
Here's a yml file, with everything, just for easy reference.:
python:
command: nosetests
wip_command: nosetests -a wip
watch_glob: "*.py;*.html" # Note you do need quotes because of the *.
watch_dir: my_app/foo
parser: my_parsers.MyNiftyCustomNoseParser
Any test framework that returns standard error codes (0 for pass, non-zero for fail) will Just Work out of the box. However, if you want fancy test counts (and someday more), writing a custom parser is easy.
Just write a class that inherits DefaultParser
, stick it somewhere on your python path, put in in your tests.yml
file, and you're good to go. Here's an example for pep8.
Please note: if you're writing for a common framework/use case, please submit a pull request!
Write your own parser.
my_parsers.py
from polytester.parsers import DefaultParser
class MyCustomParser(DefaultParser):
name = "my custom"
def tests_passed(self, result):
# Required, the code below is the default in DefaultParser
return result.return_code == 0
def num_failed(self, result):
# Optional.
m = re.match("(\d+) failed", result.output)
return int(m.group(0))
def num_passed(self, result):
# Optional.
return self.num_total(result) - self.num_failed(result)
def num_total(self, result):
# Optional.
m = re.match("(\d+) total", result.output)
return int(m.group(0))
def command_matches(self, command_string):
# Optional, used for trying to auto-detect the test framework.
# Since this is totally custom, we just return false
return False
For reference, results
is an object with the following attributes:
output
- The stdout and stderr, in the order produced while running.cleaned_output
- output
, but stripped of all ANSI colors and escape codes.return_code
- The return code.passed
- A boolean indicating if the tests have passed. None
until a definitive answer is known.parser
- An instance of the parser class. (i.e. you can call result.parser.num_failed(result)
).Specify it in your test.yml file.
custom:
command: run_tests.sh
parser: my_parsers.MyCustomParser
Run your tests like normal!
$ polytester
Detecting...
✔ custom specified as my custom tests.
Running tests...
✔ custom: 18 tests passed.
✔ All tests passed.
When tests fail, polytester just falls back to the helpful output your test frameworks already give you:
$ polytester
Detecting...
✔ api detected as django tests.
✔ e2e detected as karma tests.
✔ js detected as protractor tests.
Running tests...
✘ api - 1 of 35 tests failed.
======================================================================
FAIL: test_addition (events.tests.SampleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/me/project/events/tests.py", line 6, in test_addition
self.assertEquals(1+1, 3)
AssertionError: 2 != 3
----------------------------------------------------------------------
Ran 35 tests in 1.642s
FAILED (failures=1)
✔ e2e - 17 tests passed.
✔ js - 23 tests passed.
✘ Tests failed
Polytester leverages some fantastic libraries. It wouldn't exist without them.
Polytester has also has had help from lots of coders. Alphabetically:
--ci
.--ci
on python 3.4.--ci
, --failfast
, and a couple parsers is in.As with all the open-source projects I run, I leave the future pretty open to what the people who use the project request, and the PRs that are sent.
But here's a short list of things that are rolling around in my head as future features:
--failfast
, for super-quick iteration.If you want to add support for a language or framework, those PRs are always welcome.
If you have a bigger idea, just pop open an issue, and we'll talk it through, so we don't cross wires when the PR comes!
Anyone is welcome to contribute to polytester, regardless of skill level or experience. To make polytester the best it can be, we have one big, overriding cultural principle:
Be kind.
Simple. Easy, right?
We've all been newbie coders, we've all had bad days, we've all been frustrated with libraries, we've all spoken a language we learned later in life. In discussions with other coders, PRs, and CRs, we just give each the benefit of the doubt, listen well, and assume best intentions. It's worked out fantastically.
This doesn't mean we don't have honest, spirited discussions about the direction to move polytester forward, or how to implement a feature. We do. We just respect one other while we do it. Not so bad, right? :)
A Makefile
is included for your testing convenience. Here's a few sample commands:
$ make test # run the tests on the default python version (3.4)
$ make test-all # run tests on all supported pythons (2.7, 3.3, 3.4)
$ make flake8 # run a pep8/pyflakes style/syntax check
$ make clean # remove cached/compiled python test data
$ make clean-all # rebuild the virtualenv from scratch
The Makefile
will take care of creating a virtualenv and installing the required dependencies (and keep them up to date).
If you don't have all the supported versions of Python installed, don't worry! Push your changes to a branch, open a pull-request, and Travis will run the tests on your behalf.
FAQs
A simple, easy-to-use multi-language test runner.
We found that polytester demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.