NEW: sniffer can now be customize to run anything, see 'Advanced Usage'.
Sniffer will automatically re-run tests if your code changes. And with another third-party library (see below), the CPU usage of file system monitoring is reduced in comparison to pure-python solutions. However, sniffer will still work without any of those libraries.
Looking for maintainers
I (@jeffh) am looking for a new maintainer to carry on this project to new heights. I'm currently leaving this project on maintance mode (respond to issues, merge pull requests), but I'm not dedicating most of my free time towards this project.
Contact me on twitter (@jeffhui) or via email if you're interested in taking over the helm of this project.
pip install sniffer
sniffer in your project directory.
You can use
sniffer --help for options And like autonose, you can pass the nose
arguments with -x prefix:
The problem with autonose, is that the autodetect can be slow to detect changes. This is due to the pure python implementation - manually walking through the file system to see what's changed . Although the default install of sniffer shares the same problem, installing a third-party library can help fix the problem. The library is dependent on your operating system:
- If you use Linux, you'll need to install pyinotify.
- If you use Windows, you'll need to install pywin32.
- If you use Mac OS X 10.5+ (Leopard), you'll need to install MacFSEvents.
If you want support for other notification systems, you can install:
|||This has been resolved in subsequent autonose versions, using watchdog.|
Don't want to run nose? You can do whatever you really want. Create a scent.py file in your current working directory. Here's an example of what you can do so far:
from sniffer.api import * # import the really small API import os, termstyle # you can customize the pass/fail colors like this pass_fg_color = termstyle.green pass_bg_color = termstyle.bg_default fail_fg_color = termstyle.red fail_bg_color = termstyle.bg_default # All lists in this variable will be under surveillance for changes. watch_paths = ['.', 'tests/'] # this gets invoked on every file that gets changed in the directory. Return # True to invoke any runnable functions, False otherwise. # # This fires runnables only if files ending with .py extension and not prefixed # with a period. @file_validator def py_files(filename): return filename.endswith('.py') and not os.path.basename(filename).startswith('.') # This gets invoked for verification. This is ideal for running tests of some sort. # For anything you want to get constantly reloaded, do an import in the function. # # sys.argv and any arguments passed via -x prefix will be sent to this function as # it's arguments. The function should return logically True if the validation passed # and logicially False if it fails. # # This example simply runs nose. @runnable def execute_nose(*args): import nose return nose.run(argv=list(args))
And that's the basic case. Nothing too fancy shmanshe. You can have multiple file_validator and runnable decorators if you want.
Running with Other Test Frameworks
If you want to run another unit testing framework, you can do so by overriding
which is the class that handles running tests, or whatever you want. Specifically, you'll want to
run, method to configure what you need to be done.
test_args, are arguments gathered through
configuration options. You should perform you imports inside the function instead of outside,
to let the class reload the test framework (and reduce possibilities of multiple-run bugs).
After subclassing, set sniffer_instance parameter to your custom class when calling run or main.
For linux, there is an exception that is sometimes thrown when terminating.
Currently the program only looks for changes in the current working directory. This isn't the best solution: it doesn't understand how changes to your source code affects it.