Running python script inside a functional test in Django - python

The project that I'm recently working on load initial data by running a script:
python manage.py shell < add_initial_data.py
I'm making functional tests now and have to call this command to load initial data in the test database.
I'm trying to use subprocess.call and call_command to run that script but I can't find the option to redirect the script file to shell.
Is there a way to do that?
I've tried with
subprocess.call(['python', 'manage.py', 'shell', '<', 'add_initial_data.py'])
and
call_command('shell', '<', 'add_initial_data.py')
but gives error not recognizing < add_initial_data.py

I think you are approaching this from wrong angle. Django uses fixtures to load initial data. It is also supported in test cases django test fixture loading
If you are in python 3 and insist on your approach you might do
./manage.py shell <<EOF\ execfile('add_initial_data.py') \EOF

Related

How to debug a python project with shell script as the entry?

When I tried to debug some Deep Learning projects, I noticed that there are many projects use the shell script as the method of passing parameters. We can easily run these projects by bash run.sh in command line, but how to debug these kind of projects in IDEs like Pycharm?
I have tried to use some methods of python to call system commands like: os.system('bash run.sh') in debugger.py and simply debug the debugger.py. But the breakpoint set by pycharm in this method do not work, and will be directly ignored. What is the reason?
I also try to parse the passed parameters in the shell script and add these parameters in the debug configuration of pycharm like this:
debug configuration
but it seems too troublesome, especially when the incoming parameters are complex.
Is there any elegant solution to debug a python project with shell script as the entry?
Or is it not normative to write too complex parameter processing flow in shell script?

Using pytest, is it possible for a unit test to know that it is being run with code coverage monitoring on?

I am currently developing some tests using python py.test / unittest that, via subprocess, invoke another python application (so that I can exercise the command line options, and confirm that the tool is installed correctly).
I would like to be able to run the tests in such a way that I can get a view of the code coverage metrics (using coverage.py) for the target application using pytest_cov. By default this does not work as the code coverage instrumentation does not apply to code invoked with subprocess.
Code Coverage of the code does work if I update the tests to directly invoke the entry class for the target application (rather than running via the command line).
Ideally I want to have a single set of code which can be run in two ways:
If code coverage monitoring is not enabled then use command line
Otherwise execute the main class of the target application.
Which leads to my question(s):
Is it possible for a python unit test to determine if it is being run with code coverage enabled?
Otherwise: is there any easy way to pass a command line flag from the pytest invocation that can be used to set the mode within the code.
Coverage.py has a facility to automatically measure coverage in sub-processes that are spawned: http://coverage.readthedocs.io/en/latest/subprocess.html
Coverage sets three environment flags when running tests: COV_CORE_SOURCE, COV_CORE_CONFIG and COV_CORE_DATAFILE.
So you can use a simple if-statement to verify whether the current test is being run with coverage enabled:
import os
if "COV_CORE_SOURCE" in os.environ:
# do what yo need to do when Coverage is enabled

Restart the process where the error has been detected

In a Django project, it is possible to create unit-tests to verify what we had done so far. The principle is simple. We have to execute the command python3 manage.py test in the shell. When an error is detected in the program, the shell will display it and stop the process. However, the procedure has a little gap. If we have several errors, we have to correct it and restart the whole process. This process could take several minutes which depends of our program. Is there a manner to restart the process where the error has been detected instead of restart the whole procedure?
EDIT :
In fact, another problem I have is to retain the databases instead of recreate it. How could I do such thing?
If you want to automatically run only failing tests you need to use a third party testing driver like Nose or create your own. But it's not worth it because ...
You can specify particular tests to run by supplying any number of
“test labels” to ./manage.py test. Each test label can be a full
Python dotted path to a package, module, TestCase subclass, or test
method. For instance:
# Run just one test method
$ ./manage.py test animals.tests.AnimalTestCase.test_animals_can_speak
Source: https://docs.djangoproject.com/en/1.10/topics/testing/overview/
This approach can be used to re run only the ones that have failed.
Please note that third party test runners will probably recreate the database every time you run the test - even for only the failing test. On the other hand the django default test runner has the --keep option which allows the database to be reused. For more details see: https://stackoverflow.com/a/37100979/267540

Execute script after `python manage.py shell` is up

There is a command that calls Django's shell:
python manage.py shell
I would like to create a BASH-alias, that will:
Start python manage.py shell
Execute print 'foo'
Something similar to -i option: python -i /usr/bin/print_foo.py but with manage.py shell
The reason for doing it is too speed up the debug process. So instead of importing all relevant models and assigning variables, I want to do it in the separate PY file. So each time I start the manage.py shell, I will just have all the tools in hand.
EDIT: using python manage.py shell < /usr/bin/print_foo.py almost does the trick. However the terminal gets closed.. if there is a way to make it stay opened.
You can use the following simple shell script:
#!/bin/bash
export PYTHONSTARTUP="$1" # Set the startup script python will run when it start.
shift # Remove the first argument, don't want to pass that.
python manage.py shell "$#" # Run manage.py with the startup script.
Just supply the python script you want to run first as the first argument to the script. All other arguments are directly passed to manage.py. The change to $PYTHONSTARTUP won't affect the environment in your shell.
I also battled with this, the < test.py closes the shell, and shell_plus doesn't add much here beside auto loading of the models, doesn't load the code you want to debug
However I can do this: I make a test.py that is initializes Django if it's not ran from a Django environment, and run it with python -i test.py
The basic idea is to not use manage.py shell
if __name__ == '__main__':
# This will run e.g. from python -i test.py, but will be skipped if from Django
import django # 1.7
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
django.setup()
# Your regular Django stuff here
# Init your vars etc and prepare values to debug
# The Python prompt will remain active here so you can work on it
Another less automated solution is to call execfile('test.py') or %run test.py if you're in IPython,
pro is you can reload the test.py module without leaving the shell (faster and preserves the context), con is you have to load it manually when the shell opens up
Not a direct answer, but Django Extensions (Github, Docs) shell_plus might be interesting for that. (the package has many useful tools, so it is a valuable dependency in many cases.)
The app's models are automatically imported. To configure further imports, see the additional imports section.
If you want to automatically execute code from arbitrary python modules with shell_plus, you can use the SHELL_PLUS_PRE_IMPORTS and SHELL_PLUS_POST_IMPORTS setting. Any python modules that are configured there run a) before or b) after Django's app models are auto-imported.

How to setup DreamPie to mimic Django's "manage.py shell" functionality

I would like to use DreamPie, a python shell, as a CLI that functions the same way that manage.py shell works.
Additionally, it would be very nice to have some way to automatically run some code when the shell starts, like a set of import statements.
If you are unfamiliar with the specifics of getting this to work with DreamPie, I could also appreciate knowing what it is that manage.py shell does so I could apply it to another shell environment/interpreter.
Go to Django project directory
Execute DreamPie there
Then copy and paste manage.py on DreamPie console replacing sys.argv by ['manage.py', 'shell']

Categories

Resources