I'd like to be able to run behave from the context menu within the PyDev project explorer (i.e. right click (on a feature file or directory) Run As- Behave and have it run the feature file (or files) once run the any errors in the output would take you to the line in the file it refers to.
Is this possible?
I have set behave up as an external tool, which works but it isn't great
PyDev doesn't support behave directly but it does support pytest, so, my suggestion is using behave through pytest (you have to configure the test runner to be pytest -- see: https://www.pydev.org/manual_adv_pyunit.html).
It seems that the related pytest plugin for running behave is: https://pypi.org/project/pytest-bdd/
Eclipse (and PyDev) supports running other "External Tools" / Commands.
For behave, you just need to provide the definition to run a python script.
If anything fails, provide your own "run_behave.py" scripts that runs behave (much like the "behave script"). This also simplifies debugging.
It's possible, but as #jenisys noted, you have to make a tiny behave-runner like this (copied from the bin/behave command):
#!/path/to/your/env/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from behave.__main__ import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())
Run this, then modify the run / debug configuration with the behave command line arguments, and you're up and running (or debugging)!
Related
Is it possible to tell the python interpreter to run my script using specific command line switches.
For example,
If I have doctests enabled, I'd like to add
if __name__ == '__main__':
import doctest
doctest.testmod()
to create a self-contained test runner.
However, this requires that I add -v switch to run the script:
python myscript -v
This is not always convenient in an editor like Sublime where the build system defaults to no switches. I know I can create a custom builder but that's suboptimal compared to specifying which switches to use for certain scripts.
Is it possible and if yes, how?
UPDATE
Below someone pointed out that the doctest case involves a script flag instead of an interpreter switch. But I really want to know about both cases.
Also although testmod(verbose=True) can solve that particular case, I'm still interested in the original question.
Pass verbose=True to doctest.testmod:
if __name__ == '__main__':
import doctest
doctest.testmod(verbose=True)
Messing with the command-line flags is the wrong way to go.
You could consider using environment variables.
e.g.,
# from the command line
export VERBOSE_MODE=True
# in the Python code
import os
verbose_mode = os.environ.get('VERBOSE_MODE', False)
You could have this be a fallback mechanism if the flag isn't provided on the command line.
I sort of got what I want. On a system with bash shell, I could simply add the following to the top of my script
#! /usr/local/bin/python3 -m doctest -v
and then
chmod +x myscript.py
Don't know how to do that with Windows (maybe wait for the Linux subsystem for Win10), but fortunately I mainly work on macOS.
This works for other command line switches as well.
I've been trying to port a Maya based python project over to PyCharm but I'm having trouble running unit tests.
Maya provides its own python interpreter (mayapy.exe) with a zipped version of the python stdlib (in this case, 'Python27.zip') AFAIK there's nothing special about the stdlib here, but to run the native maya functions you have to use MayaPy rather than a generic python.
The problem appears to be that the jetBrains test runner (utRunner.py) wants to get os.system and it's barfing because it uses a specific import routine that doesn't allow for zip files. It tries this:
def import_system_module(name):
if sys.platform == "cli": # hack for the ironpython
return __import__(name)
f, filename, desc = imp.find_module(name)
return imp.load_module('pycharm_' + name, f, filename, desc)
and fails with this error:
ImportError: No module named os
I think because this is bypassing the zip import hook.
There's one solution posted here, which is basically to unzip the standard library zip. I'm reluctant to do that because I might need to run the tests on machines where I don't have admin rights. I'm also reluctant to patch the code above since I'm not clear how it fits in to the whole test process.
So: how to run tests with a zipped standardlib using PyCharm, without unzipping the library or tweaking the PyCharm install too much?
For lurkers: I was unable to find a better solution than the one linked above, so it was necessary to unzip the 2.7 standard libary into a loose folder. Inelegant, but it works,.
There was a further wrinkle that maya users need to watch out for: PyCharm does not like tests which run Maya.standalone -- the standalone session did not exit properly, so when running tests (in onr ore more files) that called
import maya.standalone
maya.standalone.initialize()
The pycharm test runner would hang on completion. After much frustration I found that adding an atexit handler to the test code would allow the standalone to exit in a way that PyCharm could tolerate:
def get_out_of_maya():
try:
import maya.commands as cmds
cmds.file(new=True, force=True)
except:
pass
os._exit(0) # note underscore
import atexit
atexit.register(get_out_of_maya)
This pre-empts the atexit hook in Maya and allows the tests to complete to the satisfaction of the Pycharm runner. FWIW, it also helps if you are running MayaPy.exe from a subprocess and executing your tests that way.
I ended up just editing Pycharm's utrunner.py file. It already imports os at the top of the file, so I'm not sure why it calls import_system_module. The import command automatically handles zip files. Also if you put the maya.standalone in the runner file, you don't need to call it in any of your test files.
#os = import_system_module("os")
#re = import_system_module("re")
import re
try:
import maya.standalone
maya.standalone.initialize()
except ImportError:
pass
I'm using Pycharm 5.0.1.
I'm trying to setup Python to execute nose, but only on an existing application I'm developing locally. I don't want nose running around all libraries that are currently installed. I do, however, want nose to discover any tests within the current working directory and child directories.
To start with, all I'm trying to do is make sure that the arguments I'm passing are being used (solved by #need-batchelder below). However, at the moment it looks like the arguments I am passing are being ignored, and global discovery of the tests is occurring (i.e. picking up tests from the python folder too.
From the docs:
-V, --version
Output nose version and exit
Running nosetests -V from the command line produces the expected version output:
nosetests -V
nosetests-script.py version 1.2.1
However, the following test script starts running every test it can find, including those of libraries installed in the python path and not part of the current working directory , even though it is located in the root of the application:
import nose, os
def main():
print os.getcwd()
x=raw_input() #This is just so I can see the output of the cwd before it launches into testing everything it can find.
result = nose.run(argv=['-V'])
if __name__ == '__main__':
main()
Here's what I've tried:
Using nose.main() , x=nose.core.run() , x=nose.run().
Passing the arguments directly to nose.run() and using a list.
Using a nose.cfg file.
Thanks
EDIT: Trying #ned-batchelder 's suggestion allows me to run nose with given arguments, but doesn't allow discovery of tests within the application folders. So if I do that, I can pass arguments but I can't test my application.
I believe nose expects argv to be the complete argv, meaning the first element should be the name of the program:
nose.run(argv=['me.py', '-V'])
Probably, what you want is:
arguments = sys.argv[:1] + my_custom_argument_list + sys.argv[1:]
nose.run(argv=arguments)
This will allow you to use your custom arguments as well as those from the command line that invokes your script. It also address the issue that Ned points out about nose requiring that the first argument point to the script.
Here is the problem...
I'm writing very small plugin for Blender,
I have 10 python scripts, they parsing different file formats by using command-line, and I have a Main Python script to run all other scripts with proper commands...
for example, "Main.py" include:
txt2cfg.py -inFile -outFile...
ma2lxo.py -inFile -outFile...
Blender already include Python, so I can run "Main.py" from Blender, But I need it to work with both PC and MAC, and also doesn't require Python installation, so I can't use:
execfile(' txt2cfg.py -inFile -outFile ')
os.system(' ma2lxo.py -inFile -outFile ')
or even import subprocess
because they required Python installation in order to run *.py files.
Sorry for language
Thanks
If you really need to execute a python script in a new process and you don't know where the interpreter you want is located then use the sys module to help out.
import sys
import subprocess
subprocess.Popen((sys.executable, "script.py"))
Though importing the module (dynamically if need be) and then running its main method in another script is probably a better idea.
for example, "Main.py" include:
txt2cfg.py -inFile -outFile...
ma2lxo.py -inFile -outFile...
Two things.
Each other script needs a main() function and a "main-import switch". See http://docs.python.org/tutorial/modules.html#executing-modules-as-scripts for hints on how this must look.
Import and execute the other scripts.
import txt2cfg
import ma2lxo
txt2cfg.main( inFile, outFile )
ma2lxo.main( inFile, outFile )
This is the simplest way to do things.
Two options:
Use py2exe to bundle the interpreter with the scripts.
Import the modules and call the functions automatically.
To clarify, the Python module I'm writing is a self-written .py file (named converter), not one that comes standard with the Python libraries.
Anyways, I want to somehow overload my function such that typing in
converter file_name
will send the file's name to
def converter(file_name):
# do something
I've been extensively searching through Google and StackOverflow, but can't find anything that doesn't require the use of special characters like $ or command line options like -c. Does anyone know how to do this?
You can use something like PyInstaller to create a exe out of your py-file.
To use the argument in python:
import sys
if __name__ == "__main__":
converter(sys.argv[1])
You can type in the windows shell:
python converter.py file_name.txt
to give the arguments to the sys.argv list within python. So to access them:
import sys
sys.argv[0] # this will be converter.py
sys.argv[1] # this will be file_name.txt
at the bottom of the file you want to run, add:
if __name__ == "__main__":
converter(sys.argv[1])
To have a second argument:
python converter.py file_name1.txt file_name2.txt
This will be the result:
import sys
sys.argv[0] # this will be converter.py
sys.argv[1] # this will be file_name1.txt
sys.argv[2] # this will be file_name2.txt
I would recommend using something like the builtin argparse (for 2.7/3.2+) or argparse on pypi (for 2.3+) if you're doing many complicated command line options.
Only way I can think of is to create a batch file of the same name and within it, call your python script with the parameters provided.
With batch files you don't have to specify the extension (.bat) so it gets you closer to where you want to be.
Also, without any compiling .py to .exe, you may make your script 'executable', so that if you issue command line like myscript param param, the system will search for myscript.py and run it for you, as if it was an .exe or .bat file.
In order to achieve this, configure the machine where you plan to run your script:
Make sure you have file associations set (.py to python interpreter, that is, if you doubleclick at your script in the explorer -- it gets executed). Normally this gets configured by the Python installer.
Edit the COMSPEC environment variable (look inside My Computer properties) to include .PY extension as well as .EXE, .COM, etc.
Start a fresh cmd.exe from Start menu to use the new value of variable. Old instances of any programs will see only old value.
This setup could be handy if you run many scripts on the same machine, and not so handy if you spread you scripts to many machines. In the latter case you better use py2exe converter to bundle up your application into a self-sufficient package (which doesn't require even python to be installed).