├── .gitignore ├── LICENSE ├── README.md ├── autoload ├── __init__.py ├── vim_python_test_runner.py └── vim_python_test_runner.vim ├── doc └── vim-python-test-runner.txt ├── plugin └── vim_python_test_runner.vim └── tests ├── __init__.py ├── classless_dummy_file.py ├── dummy_test_file.py ├── run_django_tests_in_vim_tests.py ├── run_nosetests_in_vim_tests.py └── test_run_pytest_in_vim_tests.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Jarrod Taylor 4 | 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vim-python-test-runner.vim 2 | 3 | A simple way of running tests for your python files from within VIM. 4 | 5 | This plugin was created to allow running Django tests with django-nose that 6 | require database interaction from within Vim. Thus avoiding the need to toggle 7 | between your vim session and the shell for longer periods of time. It will 8 | also run your regular python unit tests with nosetests as well when not 9 | working on a Django project. 10 | 11 | ## Demo 12 | ![django_test_run](https://f.cloud.github.com/assets/4416952/2181329/c3107922-974b-11e3-88a8-c40f27061658.gif) 13 | 14 | ## Installation 15 | 16 | Use your plugin manager of choice. 17 | 18 | - [Pathogen](https://github.com/tpope/vim-pathogen) 19 | - `git clone https://github.com/JarrodCTaylor/vim-python-test-runner ~/.vim/bundle/vim-python-test-runner` 20 | - [Vundle](https://github.com/gmarik/vundle) 21 | - Add `Plugin 'JarrodCTaylor/vim-python-test-runner'` to .vimrc 22 | - Run `:PluginInstall` 23 | - [NeoBundle](https://github.com/Shougo/neobundle.vim) 24 | - Add `NeoBundle 'https://github.com/JarrodCTaylor/vim-python-test-runner'` to .vimrc 25 | - Run `:NeoBundleInstall` 26 | - [vim-plug](https://github.com/junegunn/vim-plug) 27 | - Add `Plug 'https://github.com/JarrodCTaylor/vim-python-test-runner'` to .vimrc 28 | - Run `:PlugInstall` 29 | 30 | ## Requirements 31 | 32 | You need a VIM version that was compiled with python support, which is typical 33 | for most distributions on Linux/Mac. You can check this by running 34 | ``vim --version | grep +python`` 35 | if you get a hit you are in business. 36 | 37 | Tests are ran with either django-nose or nosetest so these will need to be 38 | pip installed in order for the plugin to function properly. 39 | 40 | ## Usage 41 | 42 | The plugin provides nine commands: 43 | 44 | - `DjangoTestApp`: Run all tests for the current app 45 | - `DjangoTestFile`: Run all tests in the current file 46 | - `DjangoTestClass`: Run all tests in the current class 47 | - `DjangoTestMethod`: Run test for the current method 48 | - `NosetestFile`: Run all tests for the current file 49 | - `NosetestClass`: Run all tests in the current class 50 | - `NosetestMethod`: Run the current test method (inside of a class) 51 | - `NosetestBaseMethod`: Run the current test method (outside of a class) 52 | - `RerunLastTests`: Rerun the last tests 53 | 54 | All arguments can be tab-completed. Ensure that your cursor is within a 55 | file, class or method as appropriate for the command being called. 56 | 57 | For ease of usage you can map the above actions to a shortcut. For example, 58 | if you wanted leader mappings you could set something like the following in 59 | your vimrc: 60 | 61 | ``` 62 | nnoremap da :DjangoTestApp 63 | nnoremap df :DjangoTestFile 64 | nnoremap dc :DjangoTestClass 65 | nnoremap dm :DjangoTestMethod 66 | nnoremap nf :NosetestFile 67 | nnoremap nc :NosetestClass 68 | nnoremap nm :NosetestMethod 69 | nnoremap nb :NosetestBaseMethod 70 | nnoremap rr :RerunLastTests 71 | ``` 72 | 73 | ### Quickfix Results 74 | 75 | Your tests results will be available in the quickfix window after they finish 76 | running and you return to your Vim buffer. Open quickfix with `:copen` and 77 | you can jump to failing tests by placing your cursor on the desired test and 78 | pressing enter. 79 | 80 | ### Required Configuration File for Django Tests 81 | 82 | To make use of the plugin for Django projects you will need to create a small 83 | config file named ``.vim-django`` in the root of your project that defines some 84 | information about the apps you would like to run tests for. Assuming a basic 85 | folder structure the config file would be saved in the following location. 86 | ``` 87 | ── Project Root 88 | ├── .vim-django 89 | ├── manage.py 90 | ├── app1 91 | │ └── tests 92 | │ └── testsa1.py 93 | └── app2 94 | └── tests 95 | ├── testsb1.py 96 | └── testsb2.py 97 | ``` 98 | 99 | ### Config file contents 100 | 101 | #### Required fields 102 | 103 | The only required field is a list of the app names that you will be running 104 | tests for. 105 | `"app_name": "app1, app2"` 106 | 107 | #### Optional fields 108 | 109 | Optional fields that can be set in the vim-django config file are as follows: 110 | - `environment`: If you have modified your manage.py file to accept an environment argument 111 | then you may use the environment flag to specify which one to run tests for. 112 | Example `"environment": "dev"` If you haven't modified your manage.py file 113 | then you don't need to use this. 114 | 115 | - `flags`: An array of flags that you would like passed to the test runner 116 | See example config file below for usage. 117 | 118 | - `test-runner`: Set if you are using the default Django test runner 119 | Example `"test-runner": "django"` 120 | 121 | 122 | #### vim-django config file example 123 | 124 | Using the example project above we would set the app name to "app1, app2" 125 | The environment field is optional. We are also saying that we want the test to use 126 | the fail fast option. 127 | 128 | ``` 129 | {"app_name": "app1, app2", 130 | "environment": "OptionalNameOfEnv", 131 | "flags": ["failfast"]} 132 | ``` 133 | *NOTE* be sure to use double quotes in the config file as it is parsed as json 134 | 135 | #### vim-django config file example for namespace packages 136 | 137 | Namespace packages are supported, but require slightly different placement of 138 | the `.vim-django` config file. Rather than placing it in the project root place 139 | it in the lowest level package. For example, given a namespace package called 140 | `organization.department.team` the `.vim-django` file would be inside of the 141 | `team` directory. 142 | ``` 143 | ── Project Root 144 | ├── manage.py 145 | └── organization 146 | └── department 147 | └── team 148 | └── .vim-django 149 | └── testsa1.py 150 | └── tests 151 | ├── testsb1.py 152 | └── testsb2.py 153 | ``` 154 | 155 | The `.vim-django` file will contain only the top level package name, in this case 156 | `organization`, for example: 157 | 158 | ``` 159 | {"app_name": "organization"} 160 | ``` 161 | 162 | ### Outside of Django 163 | 164 | Nothing other than nose is required to use this plugin for tests that are 165 | outside of a Django application. 166 | -------------------------------------------------------------------------------- /autoload/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JarrodCTaylor/vim-python-test-runner/64acd4ba3d2494fcab24ff3ce0ee52658d1f0334/autoload/__init__.py -------------------------------------------------------------------------------- /autoload/vim_python_test_runner.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python 2 | import os 3 | import re 4 | import json 5 | 6 | 7 | class NotDjango(Exception): 8 | 9 | def __str__(self): 10 | return "Are you sure this is a Django project?" 11 | 12 | 13 | class NoVimDjango(Exception): 14 | 15 | def __str__(self): 16 | return ".vim-django file does not exist or is improperly formated. ':help vim-python-test-runner.txt'" 17 | 18 | 19 | def get_command_to_run_the_current_app(current_dir): 20 | path_to_manage = find_path_to_file(current_dir, "manage.py", NotDjango) 21 | app_name = get_app_name(current_dir) 22 | env_name = get_env_name_if_exists(current_dir) 23 | flags = get_flags(current_dir) 24 | command = "{0}{1}test {2}{3}".format(path_to_manage, env_name, flags, app_name) 25 | write_test_command_to_cache_file(command) 26 | return (command) 27 | 28 | 29 | def get_command_to_run_the_current_file(current_dir): 30 | command_to_current_app = get_command_to_run_the_current_app(current_dir) 31 | path_to_tests = get_dot_notation_path_to_test(current_dir) 32 | file_name = get_file_name(current_dir) 33 | cmd = "{}.{}.{}".format(command_to_current_app, path_to_tests, file_name) 34 | write_test_command_to_cache_file(cmd) 35 | return cmd 36 | 37 | 38 | def get_command_to_run_the_current_class(current_dir, current_line, current_buffer): 39 | class_name = get_current_method_and_class(current_line, current_buffer)[0] 40 | divider = '.' if get_test_runner(current_dir) == 'django' else ':' 41 | cmd = "{}{}{}".format(get_command_to_run_the_current_file(current_dir), divider, class_name) 42 | write_test_command_to_cache_file(cmd) 43 | return cmd 44 | 45 | 46 | def get_command_to_run_the_current_method(current_dir, current_line, current_buffer): 47 | method_name = get_current_method_and_class(current_line, current_buffer)[1] 48 | command_to_current_class = get_command_to_run_the_current_class(current_dir, current_line, current_buffer) 49 | cmd = "{}.{}".format(command_to_current_class, method_name) 50 | write_test_command_to_cache_file(cmd) 51 | return cmd 52 | 53 | 54 | def get_command_to_run_current_file_with_nosetests(path_to_current_file): 55 | command = ":!nosetests {0}".format(path_to_current_file) 56 | write_test_command_to_cache_file(command) 57 | return command 58 | 59 | 60 | def get_command_to_run_current_class_with_nosetests(path_to_current_file, current_line, current_buffer): 61 | run_file = get_command_to_run_current_file_with_nosetests(path_to_current_file) 62 | current_class = get_current_method_and_class(current_line, current_buffer)[0] 63 | command = run_file + ":" + current_class 64 | write_test_command_to_cache_file(command) 65 | return command 66 | 67 | 68 | def get_command_to_run_current_method_with_nosetests(path_to_current_file, current_line, current_buffer): 69 | run_class = get_command_to_run_current_class_with_nosetests(path_to_current_file, current_line, current_buffer) 70 | current_method = get_current_method_and_class(current_line, current_buffer)[1] 71 | command = run_class + "." + current_method 72 | write_test_command_to_cache_file(command) 73 | return command 74 | 75 | 76 | def get_command_to_run_current_base_method_with_nosetests(path_to_current_file, current_line, current_buffer): 77 | run_file = get_command_to_run_current_file_with_nosetests(path_to_current_file) 78 | current_method = get_current_method_and_class(current_line, current_buffer)[1] 79 | command = run_file + ":" + current_method 80 | write_test_command_to_cache_file(command) 81 | return command 82 | 83 | 84 | def get_command_to_run_current_file_with_pytests(path_to_current_file): 85 | command = ":!pytest {0}".format(path_to_current_file) 86 | write_test_command_to_cache_file(command) 87 | return command 88 | 89 | 90 | def get_command_to_run_current_class_with_pytests(path_to_current_file, current_line, current_buffer): 91 | run_file = get_command_to_run_current_file_with_pytests(path_to_current_file) 92 | current_class = get_current_method_and_class(current_line, current_buffer)[0] 93 | command = run_file + "::" + current_class 94 | write_test_command_to_cache_file(command) 95 | return command 96 | 97 | 98 | def get_command_to_run_current_method_with_pytests(path_to_current_file, current_line, current_buffer): 99 | run_class = get_command_to_run_current_class_with_pytests(path_to_current_file, current_line, current_buffer) 100 | current_method = get_current_method_and_class(current_line, current_buffer)[1] 101 | command = run_class + "::" + current_method 102 | write_test_command_to_cache_file(command) 103 | return command 104 | 105 | 106 | def get_command_to_run_current_base_method_with_pytests(path_to_current_file, current_line, current_buffer): 107 | run_file = get_command_to_run_current_file_with_pytests(path_to_current_file) 108 | current_method = get_current_method_and_class(current_line, current_buffer)[1] 109 | command = run_file + "::" + current_method 110 | write_test_command_to_cache_file(command) 111 | return command 112 | 113 | 114 | def get_command_to_rerun_last_tests(): 115 | with open("/tmp/vim_python_test_runner_cache", "r") as f: 116 | return f.read() 117 | 118 | 119 | def write_test_command_to_cache_file(command): 120 | with open("/tmp/vim_python_test_runner_cache", "w") as f: 121 | f.write(command) 122 | 123 | 124 | def find_path_to_file(current_dir, file_to_look_for, raise_exception=False): 125 | dir_list = [directory for directory in current_dir.split(os.path.sep) if directory] 126 | for x in range(len(dir_list) - 1, -1, -1): 127 | path_to_check = os.path.sep + os.path.sep.join(dir_list[:x]) 128 | if file_to_look_for in os.listdir(path_to_check): 129 | return path_to_check + os.sep + file_to_look_for 130 | raise raise_exception 131 | 132 | 133 | def get_app_name(current_dir): 134 | apps = get_json_field_from_config_file(current_dir, "app_name") 135 | try: 136 | return [app.lstrip() for app in apps.split(",") if app.lstrip() in current_dir][0] 137 | except: 138 | raise NoVimDjango 139 | 140 | 141 | def get_dot_notation_path_to_test(current_dir): 142 | app_name = get_app_name(current_dir) 143 | if app_name: 144 | path_to_tests = current_dir.split(os.sep + app_name + os.sep)[1] 145 | return ".".join(path_to_tests.split("/")[:-1]) 146 | return False 147 | 148 | 149 | def get_file_name(current_dir): 150 | path_parts = current_dir.split(os.sep) 151 | return path_parts[-1].split(".")[0] 152 | 153 | 154 | def get_current_method_and_class(current_line_index, current_buffer): 155 | class_regex, class_name = re.compile(r"^class (?P.+)\("), False 156 | method_regex, method_name = re.compile(r"def (?P.+)\("), False 157 | for line in range(current_line_index - 1, -1, -1): 158 | if class_regex.search(current_buffer[line]) is not None and not class_name: 159 | class_name = class_regex.search(current_buffer[line]) 160 | class_name = class_name.group(1) 161 | if method_regex.search(current_buffer[line]) is not None and not method_name and not class_name: 162 | method_name = method_regex.search(current_buffer[line]) 163 | method_name = method_name.group(1) 164 | return (class_name, method_name) 165 | 166 | 167 | def get_json_field_from_config_file(current_dir, field_name): 168 | try: 169 | with open(find_path_to_file(current_dir, ".vim-django"), "r") as f: 170 | json_string = f.read() 171 | parsed_json = json.loads(json_string) 172 | return parsed_json[field_name] 173 | except Exception: 174 | return False 175 | 176 | 177 | def get_flags(current_dir): 178 | formatted_flags = "" 179 | user_flags = get_json_field_from_config_file(current_dir, "flags") or [] 180 | for flag in user_flags: 181 | formatted_flags += "--{} ".format(flag) 182 | return formatted_flags 183 | 184 | 185 | def get_env_name_if_exists(current_dir): 186 | env_name = get_json_field_from_config_file(current_dir, "environment") 187 | if env_name: 188 | return " {} ".format(env_name) 189 | return " " 190 | 191 | 192 | def get_test_runner(current_dir): 193 | runner = get_json_field_from_config_file(current_dir, "test-runner") 194 | if runner: 195 | return "{}".format(runner) 196 | return " " 197 | -------------------------------------------------------------------------------- /autoload/vim_python_test_runner.vim: -------------------------------------------------------------------------------- 1 | set makeprg=cat\ /tmp/test_results.txt 2 | set efm+=%-G%.%#lib/python%.%#/site-package%.%#,%C\ %.%#,%A\ \ File\ \"%f\"\\,\ line\ %l%.%#,%Z%[%^\ ]%\\@=%m 3 | 4 | if !has('python3') 5 | finish 6 | endif 7 | 8 | " ----------------------------- 9 | " Add our directory to the path 10 | " ----------------------------- 11 | python3 import sys 12 | python3 import vim 13 | python3 sys.path.append(vim.eval('expand(":h")')) 14 | 15 | function! vim_python_test_runner#RunDesiredTests(command_to_run) 16 | python3 << EndPython 17 | import os 18 | from vim_python_test_runner import * 19 | 20 | def get_proper_command(desired_command, current_directory): 21 | current_line_index = vim.current.window.cursor[0] 22 | FUNCTIONS = { 23 | "django_app": lambda: get_command_to_run_the_current_app(current_directory), 24 | "django_file": lambda: get_command_to_run_the_current_file(current_directory), 25 | "django_class": lambda: get_command_to_run_the_current_class(current_directory, current_line_index, vim.current.buffer), 26 | "django_method": lambda: get_command_to_run_the_current_method(current_directory, current_line_index, vim.current.buffer), 27 | "nose_file": lambda: get_command_to_run_current_file_with_nosetests(vim.current.buffer.name), 28 | "nose_class": lambda: get_command_to_run_current_class_with_nosetests(vim.current.buffer.name, current_line_index, vim.current.buffer), 29 | "nose_method": lambda: get_command_to_run_current_method_with_nosetests(vim.current.buffer.name, current_line_index, vim.current.buffer), 30 | "nose_base_method": lambda: get_command_to_run_current_base_method_with_nosetests(vim.current.buffer.name, current_line_index, vim.current.buffer), 31 | "pytest_file": lambda: get_command_to_run_current_file_with_pytests(vim.current.buffer.name), 32 | "pytest_class": lambda: get_command_to_run_current_class_with_pytests(vim.current.buffer.name, current_line_index, vim.current.buffer), 33 | "pytest_method": lambda: get_command_to_run_current_method_with_pytests(vim.current.buffer.name, current_line_index, vim.current.buffer), 34 | "pytest_base_method": lambda: get_command_to_run_current_base_method_with_pytests(vim.current.buffer.name, current_line_index, vim.current.buffer), 35 | "rerun": lambda: get_command_to_rerun_last_tests() 36 | } 37 | return FUNCTIONS[desired_command]() 38 | 39 | def run_desired_command_for_os(command_to_run): 40 | if "nose" in vim.eval("a:command_to_run") or "nose" in command_to_run: 41 | # Run nosetests for Python. 42 | vim.command("{0} 2>&1 | tee /tmp/test_results.txt".format(command_to_run)) 43 | elif "pytest" in vim.eval("a:command_to_run") or "pytest" in command_to_run: 44 | # Run pytests for Python. 45 | vim.command("{0} 2>&1 | tee /tmp/test_results.txt".format(command_to_run)) 46 | else: 47 | # Run manage.py test for Django. 48 | vim.command(":!python {0} 2>&1 | tee /tmp/test_results.txt".format(command_to_run)) 49 | 50 | def main(): 51 | current_directory = os.sep.join([dir for dir in vim.current.buffer.name.split(os.sep) if dir]) 52 | try: 53 | command_to_run = get_proper_command(vim.eval("a:command_to_run"), current_directory) 54 | except Exception as e: 55 | print(e) 56 | run_desired_command_for_os(command_to_run) 57 | vim.command('silent make! | cw') 58 | 59 | vim.command('wall') 60 | main() 61 | EndPython 62 | endfunction 63 | 64 | -------------------------------------------------------------------------------- /doc/vim-python-test-runner.txt: -------------------------------------------------------------------------------- 1 | *vim-python-test-runner.txt* A Django aware testsrunner for vim. 2 | Allows you to run Django unit tests that require database interactions, with 3 | django-nose as well as unit tests outside of a Django project with nosetests. 4 | 5 | =============================================================================== 6 | CONTENTS 7 | 8 | 9 | 1. Intro .............................................. |test-runner-intro| 10 | 2. Requirements ................................ |test-runner-requirements| 11 | 3. Usage .............................................. |test-runner-usage| 12 | 4. Config File .................................. |test-runner-config-file| 13 | 4.1 Config file contents........................ |config-file-contents| 14 | 4.1.1 ........................................... |required-fields| 15 | 4.1.2 ........................................... |optional-fields| 16 | 4.1.3 ............................ |vim-django-config-file-example| 17 | 4.1.4 .......... |vim-django-namespace-package-config-file-example| 18 | 4.2 Outside of Django................. |plugin-usage-outside-of-django| 19 | 5. Licence .......................................... |test-runner-licence| 20 | 6. Bugs ................................................ |test-runner-bugs| 21 | =============================================================================== 22 | 1. Intro *test-runner-intro* 23 | 24 | A simple way of running tests for your python files from within VIM. 25 | 26 | This plugin was created to allow running Django tests with django-nose that 27 | require database interaction from within Vim. Thus avoiding the need to toggle 28 | between your vim session and the shell for longer periods of time. It will 29 | also run your regular python unit tests with nosetests as well when not 30 | working on a Django project. 31 | 32 | =============================================================================== 33 | 2. Requirements *test-runner-requirements* 34 | 35 | You need a VIM version that was compiled with python support, which is typical 36 | for most distributions on Linux/Mac. You can check this by running 37 | ``vim --version | grep +python`` 38 | if you get a hit you are in business. 39 | 40 | Tests are ran with either django-nose or nosetest so these will need to be 41 | pip installed in order for the plugin to function properly. 42 | 43 | =============================================================================== 44 | 3. Usage *test-runner-usage* 45 | 46 | The plugin provides nine commands: 47 | 48 | - `DjangoTestApp`: Run all tests for the current app 49 | - `DjangoTestFile`: Run all tests in the current file 50 | - `DjangoTestClass`: Run all tests in the current class 51 | - `DjangoTestMethod`: Run test for the current method 52 | - `NosetestFile`: Run all tests for the current file 53 | - `NosetestClass`: Run all tests in the current class 54 | - `NosetestMethod`: Run the current test method (inside of a class) 55 | - `NosetestBaseMethod`: Run the current test method (outside of a class) 56 | - `RerunLastTests`: Rerun the last tests 57 | 58 | All arguments can be tab-completed. Ensure that your cursor is within a 59 | file, class or method as appropriate for the command being called. 60 | 61 | For ease of usage you can map the above actions to a shortcut. For example, 62 | if you wanted leader mappings you could set something like the following in 63 | your vimrc: 64 | 65 | nnoremapda :DjangoTestApp 66 | nnoremapdf :DjangoTestFile 67 | nnoremapdc :DjangoTestClass 68 | nnoremapdm :DjangoTestMethod 69 | nnoremapnf :NosetestFile 70 | nnoremapnc :NosetestClass 71 | nnoremapnm :NosetestMethod 72 | nnoremapnb :NosetestBaseMethod 73 | nnoremaptf :PytestFile 74 | nnoremaptc :PytestClass 75 | nnoremaptm :PytestMethod 76 | nnoremaptb :PytestBaseMethod 77 | nnoremaprr :RerunLastTests 78 | 79 | Your tests results will be available in the quickfix window after they finish 80 | running and you return to your Vim buffer. Open quickfix with `:copen` and 81 | you can jump to failing tests by placing your cursor on the desired test and 82 | pressing enter. 83 | 84 | =============================================================================== 85 | 4. Config File *test-runner-config-file* 86 | 87 | To make use of the plugin for Django projects you will need to create a small 88 | config file named ``.vim-django`` in the root of your project that defines some 89 | information about the apps you would like to run tests for. Assuming a basic 90 | folder structure the config file would be saved in the following location. 91 | ``` 92 | ── Project Root 93 | ├── .vim-django 94 | ├── manage.py 95 | ├── app1 96 | │ └── tests 97 | │ └── testsa1.py 98 | └── app2 99 | └── tests 100 | ├── testsb1.py 101 | └── testsb2.py 102 | ``` 103 | 104 | -------------------------------------------------------------------------------- 105 | 4.1 Config file contents *config-file-contents* 106 | 107 | 4.1.1 *required-fields* 108 | 109 | The only required field is a list of the app names that you will be running 110 | tests for. 111 | `"app_name": "app1, app2"` 112 | 113 | 4.1.2 *optional-fields* 114 | 115 | Optional fields that can be set in the vim-django config file are as follows: 116 | - `environment`: If you have modifyed your manage.py file to accept an 117 | environment argument then you may use the environment flag to 118 | specify which one to run tests for. Example `"environment": "dev"` 119 | If you haven't modifyed your manage.py file then you don't need to 120 | use this. 121 | 122 | - `flags`: An array of flags that you would like passed to the test runner 123 | See example config file below for usage. 124 | 125 | 4.1.3 *vim-django-config-file-example* 126 | 127 | Using the example project above we would set the app name to "app1, app2" 128 | The environment field is optional. We are also saying that we want the test to use 129 | the fail fast option. 130 | 131 | ``` 132 | {"app_name": "app1, app2", 133 | "environment": "OptionalNameOfEnv", 134 | "flags": ["failfast"]} 135 | ``` 136 | *NOTE* be sure to use double quotes in the config file as it is parsed as json 137 | 138 | 4.1.4 *vim-django-namespace-package-config-file-example* 139 | 140 | Namespace packages are supported, but require slightly different placement of 141 | the `.vim-django` config file. Rather than placing it in the project root place 142 | it in the lowest level package. For example, given a namespace package called 143 | `organization.department.team` the `.vim-django` file would be inside of the 144 | `team` directory. 145 | ``` 146 | ── Project Root 147 | ├── manage.py 148 | └── organization 149 | └── department 150 | └── team 151 | └── .vim-django 152 | └── testsa1.py 153 | └── tests 154 | ├── testsb1.py 155 | └── testsb2.py 156 | ``` 157 | 158 | The `.vim-django` file will contain only the top level package name, in this case 159 | `organization`, for example: 160 | 161 | ``` 162 | {"app_name": "organization"} 163 | ``` 164 | 165 | -------------------------------------------------------------------------------- 166 | 4.2 Outside of Django *plugin-usage-outside-of-django* 167 | 168 | Nothing other than nose is required to use this plugin for tests that are 169 | outside of a Django application. 170 | 171 | =============================================================================== 172 | 5. Licence *test-runner-licence* 173 | 174 | The MIT License (MIT) 175 | 176 | Copyright (c) 2013 Jarrod Taylor 177 | 178 | 179 | Permission is hereby granted, free of charge, to any person obtaining a copy 180 | of this software and associated documentation files (the "Software"), to deal 181 | in the Software without restriction, including without limitation the rights 182 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 183 | copies of the Software, and to permit persons to whom the Software is 184 | furnished to do so, subject to the following conditions: 185 | 186 | The above copyright notice and this permission notice shall be included in 187 | all copies or substantial portions of the Software. 188 | 189 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 190 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 191 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 192 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 193 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 194 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 195 | THE SOFTWARE. 196 | =============================================================================== 197 | 6. Bugs *test-runner-bugs* 198 | 199 | If you find a bug please post it on the issue tracker: 200 | https://github.com/JarrodCTaylor/vim-python-test-runner/issues 201 | =============================================================================== 202 | 203 | " vim: ft=help" 204 | -------------------------------------------------------------------------------- /plugin/vim_python_test_runner.vim: -------------------------------------------------------------------------------- 1 | command! DjangoTestApp call vim_python_test_runner#RunDesiredTests("django_app") 2 | command! DjangoTestFile call vim_python_test_runner#RunDesiredTests("django_file") 3 | command! DjangoTestClass call vim_python_test_runner#RunDesiredTests("django_class") 4 | command! DjangoTestMethod call vim_python_test_runner#RunDesiredTests("django_method") 5 | command! NosetestFile call vim_python_test_runner#RunDesiredTests("nose_file") 6 | command! NosetestClass call vim_python_test_runner#RunDesiredTests("nose_class") 7 | command! NosetestMethod call vim_python_test_runner#RunDesiredTests("nose_method") 8 | command! NosetestBaseMethod call vim_python_test_runner#RunDesiredTests("nose_base_method") 9 | command! PytestFile call vim_python_test_runner#RunDesiredTests("pytest_file") 10 | command! PytestClass call vim_python_test_runner#RunDesiredTests("pytest_class") 11 | command! PytestMethod call vim_python_test_runner#RunDesiredTests("pytest_method") 12 | command! PytestBaseMethod call vim_python_test_runner#RunDesiredTests("pytest_base_method") 13 | command! RerunLastTests call vim_python_test_runner#RunDesiredTests("rerun") 14 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JarrodCTaylor/vim-python-test-runner/64acd4ba3d2494fcab24ff3ce0ee52658d1f0334/tests/__init__.py -------------------------------------------------------------------------------- /tests/classless_dummy_file.py: -------------------------------------------------------------------------------- 1 | def dummy_base_method1(): 2 | print('This is a testI') 3 | print('This is a testII') 4 | print('This is a testIII') 5 | print('This is a testIV') 6 | print('This is a testV') 7 | -------------------------------------------------------------------------------- /tests/dummy_test_file.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | class Example1(object): 5 | 6 | def dummy1(self): 7 | print('This is a test1') 8 | print('Ramdom use of the word class') 9 | print('This is a test2') 10 | print('This is a test3') 11 | some_kind_of_function_class("things") 12 | print('This is a test4') 13 | print('This is a test5') 14 | 15 | def dummy2(self): 16 | print('This is a testA') 17 | some_kind_of_function_class("things") 18 | print('This is a testB') 19 | print('This is a testC') 20 | print('This is a testD') 21 | print('This is a testE') 22 | 23 | 24 | class Example2(object): 25 | 26 | def dummy1b(self): 27 | print('This is a test1b') 28 | print('This is a test2b') 29 | print('This is a test3b') 30 | print('This is a test4b') 31 | print('This is a test5b') 32 | 33 | def dummy2b(self): 34 | print('This is a testAb') 35 | print('This is a testBb') 36 | print('This is a testCb') 37 | print('This is a testDb') 38 | print('This is a testEb') 39 | 40 | 41 | class Example3(object): 42 | 43 | def double_dummy1(self): 44 | print('This is a test1b') 45 | print('This is a test2b') 46 | print('This is a test3b') 47 | print('This is a test4b') 48 | print('This is a test5b') 49 | 50 | def double_dummy(self): 51 | print('This is a testAb') 52 | print('This is a testBb') 53 | print('This is a testCb') 54 | print('This is a testDb') 55 | print('This is a testEb') 56 | -------------------------------------------------------------------------------- /tests/run_django_tests_in_vim_tests.py: -------------------------------------------------------------------------------- 1 | import os 2 | import glob 3 | import shutil 4 | import unittest 5 | from inspect import getfile, currentframe 6 | 7 | import autoload.vim_python_test_runner as sut 8 | 9 | 10 | class VimTestRunnerForDjangoTests(unittest.TestCase): 11 | 12 | def setUp(self): 13 | dirs_to_make = [ 14 | "/tmp/project_app_only/example_app1/tests/", "/tmp/project_app_name_and_env/example_app1/tests/", 15 | "/tmp/bad_project_no_files/example_app1/tests/", "/tmp/bad_project_no_config_file/example_app1/tests/", 16 | "/tmp/bad_project_no_app/example_app1/tests/", "/tmp/bad_project_no_path_to_tests/example_app1/tests/", 17 | "/tmp/project_multiple_apps/example_app1/tests/", "/tmp/bad_project_multiple_invalid_apps/example_app1/tests/", 18 | "/tmp/project_nested_test_dirs/example_app1/tests/nested1/", "/tmp/project_contains_app_name/app_name/tests/", 19 | "/tmp/project_failfast/example_app/tests/", "/tmp/project_nocapture/example_app/tests/", 20 | "/tmp/project_with_dots/example.app.something/tests/", "/tmp/django_runner_project_app/example_app1/tests/" 21 | ] 22 | 23 | contents_to_write = [ 24 | ("/tmp/project_app_only/.vim-django", '{"app_name": "example_app1"}'), 25 | ("/tmp/project_app_only/manage.py", "#Place holder"), 26 | ("/tmp/project_app_name_and_env/.vim-django", '{"app_name": "example_app1", "environment": "test"}'), 27 | ("/tmp/project_app_name_and_env/manage.py", "#Place holder"), 28 | ("/tmp/bad_project_no_config_file/manage.py", "#Place holder"), 29 | ("/tmp/bad_project_no_app/.vim-django", '{"bad_field": "example_app1"}'), 30 | ("/tmp/bad_project_no_app/manage.py", "#Place holder"), 31 | ("/tmp/bad_project_no_path_to_tests/.vim-django", '{"app_name": "example_app1"}'), 32 | ("/tmp/bad_project_no_path_to_tests/manage.py", "#Place holder"), 33 | ("/tmp/project_multiple_apps/.vim-django", '{"app_name": "other_app, example_app1, example_app2"}'), 34 | ("/tmp/project_multiple_apps/manage.py", "#Place holder"), 35 | ("/tmp/bad_project_multiple_invalid_apps/.vim-django", '{"app_name": "other_app1, other_app2, other_app3"}'), 36 | ("/tmp/bad_project_multiple_invalid_apps/manage.py", "#Place holder"), 37 | ("/tmp/project_nested_test_dirs/.vim-django", '{"app_name": "example_app1, example_app2"}'), 38 | ("/tmp/project_nested_test_dirs/manage.py", "#Place holder"), 39 | ("/tmp/project_contains_app_name/.vim-django", '{"app_name": "example_app1, app_name"}'), 40 | ("/tmp/project_contains_app_name/manage.py", "#Place holder"), 41 | ("/tmp/project_failfast/.vim-django", '{"app_name": "example_app", "flags": ["failfast"]}'), 42 | ("/tmp/project_failfast/manage.py", "#Place holder"), 43 | ("/tmp/project_nocapture/.vim-django", '{"app_name": "example_app", "flags": ["nocapture"]}'), 44 | ("/tmp/project_nocapture/manage.py", "#Place holder"), 45 | ("/tmp/project_with_dots/.vim-django", '{"app_name": "example.app.something"}'), 46 | ("/tmp/project_with_dots/manage.py", "#Place holder"), 47 | ("/tmp/django_runner_project_app/.vim-django", '{"app_name": "example_app1", "test-runner": "django"}'), 48 | ("/tmp/django_runner_project_app/manage.py", "#Place holder") 49 | ] 50 | 51 | for directory in dirs_to_make: 52 | os.makedirs(directory) 53 | 54 | for needed_file in contents_to_write: 55 | with open(needed_file[0], "w") as f: 56 | f.write(needed_file[1]) 57 | 58 | def tearDown(self): 59 | for a_dir in glob.glob("/tmp/*project_*"): 60 | shutil.rmtree(a_dir) 61 | 62 | def test_find_vim_django_file(self): 63 | return_value = sut.find_path_to_file("/tmp/project_app_only/example_app1/tests", ".vim-django") 64 | self.assertEqual(return_value, "/tmp/project_app_only/.vim-django") 65 | 66 | def test_can_not_find_vim_django_file(self): 67 | with self.assertRaises(sut.NoVimDjango): 68 | sut.find_path_to_file("/tmp/bad_project_no_files/example_app1/tests", ".vim-django", sut.NoVimDjango) 69 | 70 | def test_find_manage_py(self): 71 | return_value = sut.find_path_to_file("/tmp/project_app_only/example_app1/tests", "manage.py") 72 | self.assertEqual(return_value, "/tmp/project_app_only/manage.py") 73 | 74 | def test_can_not_find_manage_py(self): 75 | with self.assertRaises(sut.NotDjango): 76 | sut.find_path_to_file("/tmp/bad_project_no_files/example_app1/tests", "manage.py", sut.NotDjango) 77 | 78 | def test_get_valid_class_name(self): 79 | current_line1 = 17 80 | current_line2 = 24 81 | current_buffer = self.build_buffer_helper() 82 | self.assertEqual("Example1", sut.get_current_method_and_class(current_line1, current_buffer)[0]) 83 | self.assertEqual("Example2", sut.get_current_method_and_class(current_line2, current_buffer)[0]) 84 | 85 | def test_get_current_method_and_class_returns_false_for_class_when_not_in_class(self): 86 | current_buffer = self.build_buffer_helper() 87 | self.assertEqual(False, sut.get_current_method_and_class(2, current_buffer)[0]) 88 | 89 | def test_get_valid_method_name(self): 90 | should_return_dummy2 = 15 91 | should_return_dummy1b = 27 92 | current_buffer = self.build_buffer_helper() 93 | self.assertEqual("dummy2", sut.get_current_method_and_class(should_return_dummy2, current_buffer)[1]) 94 | self.assertEqual("dummy1b", sut.get_current_method_and_class(should_return_dummy1b, current_buffer)[1]) 95 | 96 | def test_get_current_method_and_class_returns_false_when_not_in_method(self): 97 | current_buffer = self.build_buffer_helper() 98 | self.assertEqual(False, sut.get_current_method_and_class(25, current_buffer)[1]) 99 | 100 | def test_get_app_name(self): 101 | app_name = sut.get_json_field_from_config_file("/tmp/project_app_only/example_app1/tests", "app_name") 102 | self.assertEqual("example_app1", app_name) 103 | 104 | def test_get_env_name_when_present(self): 105 | app_name = sut.get_json_field_from_config_file("/tmp/project_app_name_and_env/example_app1/tests", "environment") 106 | self.assertEqual("test", app_name) 107 | 108 | def test_get_env_name_returns_false_when_not_provided(self): 109 | app_name = sut.get_json_field_from_config_file("/tmp/project_app_only/example_app1/tests", "environment") 110 | self.assertEqual(False, app_name) 111 | 112 | def test_get_command_to_run_the_current_app_when_manage_py_found_and_app_name_provided_and_no_env_specified(self): 113 | current_dir = '/tmp/project_app_only/example_app1/tests/test_file.py' 114 | command_to_run = sut.get_command_to_run_the_current_app(current_dir) 115 | self.assertEqual("/tmp/project_app_only/manage.py test example_app1", command_to_run) 116 | 117 | def test_get_command_to_run_the_current_app_when_manage_py_found_and_app_name_and_env_specified(self): 118 | current_dir = '/tmp/project_app_name_and_env/example_app1/tests/test_file.py' 119 | command_to_run = sut.get_command_to_run_the_current_app(current_dir) 120 | self.assertEqual("/tmp/project_app_name_and_env/manage.py test test example_app1", command_to_run) 121 | 122 | def test_get_command_to_run_the_current_app_when_config_file_not_properly_formated(self): 123 | current_dir = '/tmp/bad_project_no_app/example_app1/tests/test_file.py' 124 | with self.assertRaises(sut.NoVimDjango): 125 | sut.get_command_to_run_the_current_app(current_dir) 126 | 127 | def test_get_command_to_run_the_current_app_when_config_file_not_present(self): 128 | current_dir = '/tmp/bad_project_no_config_file/example_app1/tests/test_file.py' 129 | with self.assertRaises(sut.NoVimDjango): 130 | sut.get_command_to_run_the_current_app(current_dir) 131 | 132 | def test_get_command_to_run_the_current_app_when_manage_py_not_found(self): 133 | current_dir = '/tmp/bad_project_no_files/example_app1/tests/test_file.py' 134 | with self.assertRaises(sut.NotDjango): 135 | sut.get_command_to_run_the_current_app(current_dir) 136 | 137 | def test_get_command_to_run_the_current_file_when_manage_py_found_and_app_name_provided_and_no_env_specified(self): 138 | current_dir = '/tmp/project_app_only/example_app1/tests/test_file.py' 139 | expected_return_value = "/tmp/project_app_only/manage.py test example_app1.tests.test_file" 140 | command_returned = sut.get_command_to_run_the_current_file(current_dir) 141 | self.assertEqual(command_returned, expected_return_value) 142 | 143 | def test_get_command_to_run_the_current_file_when_manage_py_found_and_app_name_and_env_specified(self): 144 | current_dir = '/tmp/project_app_name_and_env/example_app1/tests/test_file.py' 145 | command_to_run = sut.get_command_to_run_the_current_file(current_dir) 146 | self.assertEqual("/tmp/project_app_name_and_env/manage.py test test example_app1.tests.test_file", command_to_run) 147 | pass 148 | 149 | def test_get_command_to_run_the_current_file_when_config_file_not_properly_formated(self): 150 | current_dir = '/tmp/bad_project_no_app/example_app1/tests/test_file.py' 151 | with self.assertRaises(sut.NoVimDjango): 152 | sut.get_command_to_run_the_current_file(current_dir) 153 | 154 | def test_get_command_to_run_the_current_file_when_config_file_not_present(self): 155 | current_dir = '/tmp/bad_project_no_config_file/example_app1/tests/test_file.py' 156 | with self.assertRaises(sut.NoVimDjango): 157 | sut.get_command_to_run_the_current_file(current_dir) 158 | 159 | def test_get_command_to_run_the_current_file_when_manage_py_not_found(self): 160 | current_dir = '/tmp/bad_project_no_files/example_app1/tests/test_file.py' 161 | with self.assertRaises(sut.NotDjango): 162 | sut.get_command_to_run_the_current_file(current_dir) 163 | 164 | def test_get_command_to_run_the_current_class_with_manage_py_app_name_but_no_env_specified(self): 165 | current_dir = '/tmp/project_app_only/example_app1/tests/test_file.py' 166 | current_line = 17 167 | current_buffer = self.build_buffer_helper() 168 | expected_return_value = "/tmp/project_app_only/manage.py test example_app1.tests.test_file:Example1" 169 | self.assertEqual(expected_return_value, sut.get_command_to_run_the_current_class(current_dir, current_line, current_buffer)) 170 | 171 | def test_get_command_to_run_the_current_class_with_manage_py_app_name_and_env_specified(self): 172 | current_dir = '/tmp/project_app_name_and_env/example_app1/tests/test_file.py' 173 | current_line = 17 174 | current_buffer = self.build_buffer_helper() 175 | expected_return_value = "/tmp/project_app_name_and_env/manage.py test test example_app1.tests.test_file:Example1" 176 | self.assertEqual(expected_return_value, sut.get_command_to_run_the_current_class(current_dir, current_line, current_buffer)) 177 | 178 | def test_get_command_to_run_the_current_class_when_config_not_properly_formated_no_app_name(self): 179 | current_dir = '/tmp/bad_project_no_app/example_app1/tests/test_file.py' 180 | current_line = 17 181 | current_buffer = self.build_buffer_helper() 182 | with self.assertRaises(sut.NoVimDjango): 183 | sut.get_command_to_run_the_current_class(current_dir, current_line, current_buffer) 184 | 185 | def test_get_command_to_run_the_current_class_when_config_not_present(self): 186 | current_dir = '/tmp/bad_project_no_app/example_app1/tests/test_file.py' 187 | current_line = 17 188 | current_buffer = self.build_buffer_helper() 189 | with self.assertRaises(sut.NoVimDjango): 190 | sut.get_command_to_run_the_current_class(current_dir, current_line, current_buffer) 191 | 192 | def test_get_command_to_run_the_current_class_when_manage_py_not_found(self): 193 | current_dir = '/tmp/bad_project_no_files/example_app1/tests/test_file.py' 194 | current_line = 17 195 | with self.assertRaises(sut.NotDjango): 196 | current_buffer = self.build_buffer_helper() 197 | self.assertEqual("Not Django", sut.get_command_to_run_the_current_class(current_dir, current_line, current_buffer)) 198 | 199 | def test_get_command_to_run_the_current_method_with_manage_py_app_name_but_no_env_specified(self): 200 | current_dir = '/tmp/project_app_only/example_app1/tests/test_file.py' 201 | current_line = 17 202 | current_buffer = self.build_buffer_helper() 203 | expected_return_value = "/tmp/project_app_only/manage.py test example_app1.tests.test_file:Example1.dummy2" 204 | self.assertEqual(expected_return_value, sut.get_command_to_run_the_current_method(current_dir, current_line, current_buffer)) 205 | 206 | def test_get_command_to_run_the_current_method_with_manage_py_app_name_and_env_specified(self): 207 | current_dir = '/tmp/project_app_name_and_env/example_app1/tests/test_file.py' 208 | current_line = 17 209 | current_buffer = self.build_buffer_helper() 210 | expected_return_value = "/tmp/project_app_name_and_env/manage.py test test example_app1.tests.test_file:Example1.dummy2" 211 | self.assertEqual(expected_return_value, sut.get_command_to_run_the_current_method(current_dir, current_line, current_buffer)) 212 | 213 | def test_get_command_to_run_the_current_method_when_config_not_properly_formated(self): 214 | current_dir = '/tmp/bad_project_no_app/example_app1/tests/test_file.py' 215 | current_line = 17 216 | current_buffer = self.build_buffer_helper() 217 | with self.assertRaises(sut.NoVimDjango): 218 | sut.get_command_to_run_the_current_method(current_dir, current_line, current_buffer) 219 | 220 | def test_get_command_to_run_the_current_method_when_config_not_present(self): 221 | current_dir = '/tmp/bad_project_no_app/example_app1/tests/test_file.py' 222 | current_line = 17 223 | current_buffer = self.build_buffer_helper() 224 | with self.assertRaises(sut.NoVimDjango): 225 | sut.get_command_to_run_the_current_method(current_dir, current_line, current_buffer) 226 | 227 | def test_get_command_to_run_the_current_method_when_manage_py_not_found(self): 228 | current_dir = '/tmp/bad_project_no_files/example_app1/tests/test_file.py' 229 | current_line = 17 230 | current_buffer = self.build_buffer_helper() 231 | with self.assertRaises(sut.NotDjango): 232 | sut.get_command_to_run_the_current_method(current_dir, current_line, current_buffer) 233 | 234 | def test_get_command_to_run_the_current_app_when_multiple_apps_are_listed_and_a_valid_app_name_is_in_config_file(self): 235 | current_dir = "/tmp/project_multiple_apps/example_app1/tests/test_file.py" 236 | expected_return_value = "/tmp/project_multiple_apps/manage.py test example_app1" 237 | command_returned = sut.get_command_to_run_the_current_app(current_dir) 238 | self.assertEqual(command_returned, expected_return_value) 239 | 240 | def test_get_command_to_run_the_current_file_when_multiple_apps_are_listed_and_a_valid_app_name_is_in_config_file(self): 241 | current_dir = "/tmp/project_multiple_apps/example_app1/tests/test_file.py" 242 | expected_return_value = "/tmp/project_multiple_apps/manage.py test example_app1.tests.test_file" 243 | command_returned = sut.get_command_to_run_the_current_file(current_dir) 244 | self.assertEqual(command_returned, expected_return_value) 245 | 246 | def test_get_command_to_run_the_current_class_when_multiple_apps_are_listed_and_a_valid_app_name_is_in_config_file(self): 247 | current_dir = "/tmp/project_multiple_apps/example_app1/tests/test_file.py" 248 | current_line = 17 249 | current_buffer = self.build_buffer_helper() 250 | expected_return_value = "/tmp/project_multiple_apps/manage.py test example_app1.tests.test_file:Example1" 251 | command_returned = sut.get_command_to_run_the_current_class(current_dir, current_line, current_buffer) 252 | self.assertEqual(command_returned, expected_return_value) 253 | 254 | def test_get_command_to_run_the_current_method_when_multiple_apps_are_listed_and_a_valid_app_name_is_in_config_file(self): 255 | current_dir = "/tmp/project_multiple_apps/example_app1/tests/test_file.py" 256 | current_line = 17 257 | current_buffer = self.build_buffer_helper() 258 | expected_return_value = "/tmp/project_multiple_apps/manage.py test example_app1.tests.test_file:Example1.dummy2" 259 | command_returned = sut.get_command_to_run_the_current_method(current_dir, current_line, current_buffer) 260 | self.assertEqual(command_returned, expected_return_value) 261 | 262 | def test_get_command_to_run_the_current_app_when_multiple_apps_are_listed_and_a_valid_app_name_is_not_in_config_file(self): 263 | current_dir = "/tmp/bad_project_multiple_invalid_apps/example_app1/tests/test_file.py" 264 | with self.assertRaises(sut.NoVimDjango): 265 | sut.get_command_to_run_the_current_app(current_dir) 266 | 267 | def test_get_command_to_run_the_current_file_when_multiple_apps_are_listed_and_a_valid_app_name_is_not_in_config_file(self): 268 | current_dir = "/tmp/bad_project_multiple_invalid_apps/example_app1/tests/test_file.py" 269 | with self.assertRaises(sut.NoVimDjango): 270 | sut.get_command_to_run_the_current_file(current_dir) 271 | 272 | def test_get_command_to_run_the_current_class_when_multiple_apps_are_listed_and_a_valid_app_name_is_not_in_config_file(self): 273 | current_dir = "/tmp/bad_project_multiple_invalid_apps/example_app1/tests/test_file.py" 274 | current_line = 17 275 | current_buffer = self.build_buffer_helper() 276 | with self.assertRaises(sut.NoVimDjango): 277 | sut.get_command_to_run_the_current_class(current_dir, current_line, current_buffer) 278 | 279 | def test_get_command_to_run_the_current_method_when_multiple_apps_are_listed_and_a_valid_app_name_is_not_in_config_file(self): 280 | current_dir = "/tmp/bad_project_multiple_invalid_apps/example_app1/tests/test_file.py" 281 | current_line = 17 282 | current_buffer = self.build_buffer_helper() 283 | with self.assertRaises(sut.NoVimDjango): 284 | sut.get_command_to_run_the_current_method(current_dir, current_line, current_buffer) 285 | 286 | def test_get_command_to_run_current_app_when_tests_are_in_a_nested_directory(self): 287 | current_dir = "/tmp/project_nested_test_dirs/example_app1/tests/nested1/test_nested_file.py" 288 | expected_return_value = "/tmp/project_nested_test_dirs/manage.py test example_app1" 289 | command_returned = sut.get_command_to_run_the_current_app(current_dir) 290 | self.assertEqual(command_returned, expected_return_value) 291 | 292 | def test_get_command_to_run_current_file_when_tests_are_in_a_nested_directory(self): 293 | current_dir = "/tmp/project_nested_test_dirs/example_app1/tests/nested1/test_nested_file.py" 294 | expected_return_value = "/tmp/project_nested_test_dirs/manage.py test example_app1.tests.nested1.test_nested_file" 295 | command_returned = sut.get_command_to_run_the_current_file(current_dir) 296 | self.assertEqual(command_returned, expected_return_value) 297 | 298 | def test_get_command_to_run_current_class_when_tests_are_in_a_nested_directory(self): 299 | current_dir = "/tmp/project_nested_test_dirs/example_app1/tests/nested1/test_nested_file.py" 300 | current_line = 17 301 | current_buffer = self.build_buffer_helper() 302 | expected_return_value = "/tmp/project_nested_test_dirs/manage.py test example_app1.tests.nested1.test_nested_file:Example1" 303 | command_returned = sut.get_command_to_run_the_current_class(current_dir, current_line, current_buffer) 304 | self.assertEqual(command_returned, expected_return_value) 305 | 306 | def test_get_command_to_run_current_method_when_tests_are_in_a_nested_directory(self): 307 | current_dir = "/tmp/project_nested_test_dirs/example_app1/tests/nested1/test_nested_file.py" 308 | current_line = 17 309 | current_buffer = self.build_buffer_helper() 310 | expected_return_value = "/tmp/project_nested_test_dirs/manage.py test example_app1.tests.nested1.test_nested_file:Example1.dummy2" 311 | command_returned = sut.get_command_to_run_the_current_method(current_dir, current_line, current_buffer) 312 | self.assertEqual(command_returned, expected_return_value) 313 | 314 | def test_get_command_to_run_current_class_when_current_line_occurs_in_file_more_than_once(self): 315 | current_dir = '/tmp/project_app_only/example_app1/tests/test_file.py' 316 | current_line = 42 317 | current_buffer = self.build_buffer_helper() 318 | expected_return_value = "/tmp/project_app_only/manage.py test example_app1.tests.test_file:Example3" 319 | self.assertEqual(expected_return_value, sut.get_command_to_run_the_current_class(current_dir, current_line, current_buffer)) 320 | 321 | def test_get_command_to_run_current_method_when_current_line_occurs_in_file_more_than_once(self): 322 | current_dir = '/tmp/project_app_name_and_env/example_app1/tests/test_file.py' 323 | current_line = 50 324 | current_buffer = self.build_buffer_helper() 325 | expected_return_value = "/tmp/project_app_name_and_env/manage.py test test example_app1.tests.test_file:Example3.double_dummy" 326 | self.assertEqual(expected_return_value, sut.get_command_to_run_the_current_method(current_dir, current_line, current_buffer)) 327 | 328 | def test_get_command_to_run_the_current_class_when_project_name_contains_the_app_name(self): 329 | current_dir = "/tmp/project_contains_app_name/app_name/tests/test_file.py" 330 | current_line = 17 331 | current_buffer = self.build_buffer_helper() 332 | expected_return_value = "/tmp/project_contains_app_name/manage.py test app_name.tests.test_file:Example1" 333 | command_returned = sut.get_command_to_run_the_current_class(current_dir, current_line, current_buffer) 334 | self.assertEqual(command_returned, expected_return_value) 335 | 336 | def test_get_command_to_run_the_current_app_when_failfast_is_set_to_true_in_config_file(self): 337 | current_dir = '/tmp/project_failfast/example_app/tests/test_file.py' 338 | command_to_run = sut.get_command_to_run_the_current_app(current_dir) 339 | self.assertEqual("/tmp/project_failfast/manage.py test --failfast example_app", command_to_run) 340 | 341 | def test_get_command_to_run_the_current_app_when_nocapture_is_set_to_true_in_config_file(self): 342 | current_dir = '/tmp/project_nocapture/example_app/tests/test_file.py' 343 | command_to_run = sut.get_command_to_run_the_current_app(current_dir) 344 | self.assertEqual("/tmp/project_nocapture/manage.py test --nocapture example_app", command_to_run) 345 | 346 | def test_get_command_to_run_current_app_writes_command_to_cache_file_when_successfully_called(self): 347 | current_dir = '/tmp/project_app_only/example_app1/tests/test_file.py' 348 | command_to_run = sut.get_command_to_run_the_current_app(current_dir) 349 | last_command = self.get_cached_command() 350 | self.assertEqual(command_to_run, last_command) 351 | 352 | def test_get_command_to_run_current_file_writes_command_to_cache_file_when_successfully_called(self): 353 | current_dir = '/tmp/project_app_only/example_app1/tests/test_file.py' 354 | command_to_run = sut.get_command_to_run_the_current_file(current_dir) 355 | last_command = self.get_cached_command() 356 | self.assertEqual(command_to_run, last_command) 357 | 358 | def test_get_command_to_run_current_class_writes_command_to_cache_file_when_successfully_called(self): 359 | current_dir = '/tmp/project_app_only/example_app1/tests/test_file.py' 360 | current_line = 17 361 | current_buffer = self.build_buffer_helper() 362 | command_to_run = sut.get_command_to_run_the_current_class(current_dir, current_line, current_buffer) 363 | last_command = self.get_cached_command() 364 | self.assertEqual(command_to_run, last_command) 365 | 366 | def test_get_command_to_run_current_method_writes_command_to_cache_file_when_successfully_called(self): 367 | current_dir = '/tmp/project_app_only/example_app1/tests/test_file.py' 368 | current_line = 17 369 | current_buffer = self.build_buffer_helper() 370 | command_to_run = sut.get_command_to_run_the_current_method(current_dir, current_line, current_buffer) 371 | last_command = self.get_cached_command() 372 | self.assertEqual(command_to_run, last_command) 373 | 374 | def test_get_command_to_rerun_last_tests_returns_the_command_last_used_to_run_tests(self): 375 | current_dir = '/tmp/project_app_only/example_app1/tests/test_file.py' 376 | command_to_run = sut.get_command_to_run_the_current_app(current_dir) 377 | last_command = sut.get_command_to_rerun_last_tests() 378 | self.assertEqual(command_to_run, last_command) 379 | 380 | def test_get_command_to_run_current_method_when_app_name_has_dots(self): 381 | current_dir = "/tmp/project_with_dots/example.app.something/tests/test_dot_file.py" 382 | current_line = 17 383 | current_buffer = self.build_buffer_helper() 384 | expected_return_value = "/tmp/project_with_dots/manage.py test example.app.something.tests.test_dot_file:Example1.dummy2" 385 | command_returned = sut.get_command_to_run_the_current_method(current_dir, current_line, current_buffer) 386 | self.assertEqual(command_returned, expected_return_value) 387 | 388 | def test_get_command_to_run_current_class_writes_using_django_default_test_runner_when_runner_set_to_django_in_vim_django_file(self): 389 | current_dir = '/tmp/project_app_only/example_app1/tests/test_file.py' 390 | current_line = 17 391 | current_buffer = self.build_buffer_helper() 392 | command_to_run = sut.get_command_to_run_the_current_class(current_dir, current_line, current_buffer) 393 | last_command = self.get_cached_command() 394 | self.assertEqual(command_to_run, last_command) 395 | 396 | def test_get_command_to_run_current_method_writes_using_django_default_test_runner_when_runner_set_to_django_in_vim_django_file(self): 397 | current_dir = '/tmp/django_runner_project_app/example_app1/tests/test_file.py' 398 | current_line = 17 399 | current_buffer = self.build_buffer_helper() 400 | command_to_run = sut.get_command_to_run_the_current_method(current_dir, current_line, current_buffer) 401 | last_command = self.get_cached_command() 402 | self.assertEqual(command_to_run, last_command) 403 | 404 | def build_buffer_helper(self): 405 | current_dir = os.path.dirname(os.path.abspath(getfile(currentframe()))) 406 | with open("{}/dummy_test_file.py".format(current_dir), "r") as f: 407 | current_buffer = [] 408 | for line in f.readlines(): 409 | current_buffer.append(line) 410 | return current_buffer 411 | 412 | def get_cached_command(self): 413 | with open("/tmp/vim_python_test_runner_cache", "r") as f: 414 | return f.read() 415 | -------------------------------------------------------------------------------- /tests/run_nosetests_in_vim_tests.py: -------------------------------------------------------------------------------- 1 | import os 2 | import unittest 3 | from inspect import getfile, currentframe 4 | 5 | import autoload.vim_python_test_runner as sut 6 | 7 | 8 | class RunNosetestsInVimTests(unittest.TestCase): 9 | 10 | def test_create_command_to_run_current_file_with_nosetests(self): 11 | path_to_current_file = "/tmp/project/tests/aTestFile.py" 12 | command_to_run = sut.get_command_to_run_current_file_with_nosetests(path_to_current_file) 13 | self.assertEqual(":!nosetests /tmp/project/tests/aTestFile.py", command_to_run) 14 | 15 | def test_create_command_to_run_current_file_with_nosetests_writes_command_to_cache_file_when_successfully_called(self): 16 | path_to_current_file = "/tmp/project/tests/aTestFile.py" 17 | command_to_run = sut.get_command_to_run_current_file_with_nosetests(path_to_current_file) 18 | last_command = sut.get_command_to_rerun_last_tests() 19 | self.assertEqual(command_to_run, last_command) 20 | 21 | def test_create_command_to_run_current_class_with_nosetests(self): 22 | path_to_current_file = "/tmp/project/tests/aTestFile.py" 23 | current_line = 27 24 | current_buffer = self.build_buffer_helper() 25 | command_to_run = sut.get_command_to_run_current_class_with_nosetests(path_to_current_file, current_line, current_buffer) 26 | self.assertEqual(":!nosetests /tmp/project/tests/aTestFile.py:Example2", command_to_run) 27 | 28 | def test_create_command_to_run_current_class_with_nosetests_writes_command_to_cache_file_when_successfully_called(self): 29 | path_to_current_file = "/tmp/project/tests/aTestFile.py" 30 | current_line = 27 31 | current_buffer = self.build_buffer_helper() 32 | command_to_run = sut.get_command_to_run_current_class_with_nosetests(path_to_current_file, current_line, current_buffer) 33 | last_command = sut.get_command_to_rerun_last_tests() 34 | self.assertEqual(command_to_run, last_command) 35 | 36 | def test_create_command_to_run_current_method_with_nosetests(self): 37 | path_to_current_file = "/tmp/project/tests/aTestFile.py" 38 | current_line = 44 39 | current_buffer = self.build_buffer_helper() 40 | command_to_run = sut.get_command_to_run_current_method_with_nosetests(path_to_current_file, current_line, current_buffer) 41 | self.assertEqual(":!nosetests /tmp/project/tests/aTestFile.py:Example3.double_dummy1", command_to_run) 42 | 43 | def test_create_command_to_run_current_method_with_nosetests_writes_command_to_cache_file_when_successfully_called(self): 44 | path_to_current_file = "/tmp/project/tests/aTestFile.py" 45 | current_line = 44 46 | current_buffer = self.build_buffer_helper() 47 | command_to_run = sut.get_command_to_run_current_method_with_nosetests(path_to_current_file, current_line, current_buffer) 48 | last_command = sut.get_command_to_rerun_last_tests() 49 | self.assertEqual(command_to_run, last_command) 50 | 51 | def test_create_command_to_run_current_method_with_nosetests_when_not_in_a_class(self): 52 | path_to_current_file = "/tmp/project/tests/aTestFile.py" 53 | current_line = 5 54 | current_buffer = self.build_buffer_helper("classless_dummy_file.py") 55 | command_to_run = sut.get_command_to_run_current_base_method_with_nosetests(path_to_current_file, current_line, current_buffer) 56 | self.assertEqual(":!nosetests /tmp/project/tests/aTestFile.py:dummy_base_method1", command_to_run) 57 | 58 | def build_buffer_helper(self, dummy_file="dummy_test_file.py"): 59 | current_dir = os.path.dirname(os.path.abspath(getfile(currentframe()))) 60 | with open("{}/{}".format(current_dir, dummy_file), "r") as f: 61 | current_buffer = [] 62 | for line in f.readlines(): 63 | current_buffer.append(line) 64 | return current_buffer 65 | 66 | def get_cached_command(self): 67 | with open("/tmp/vim_python_test_runner_cache", "r") as f: 68 | return f.read() 69 | -------------------------------------------------------------------------------- /tests/test_run_pytest_in_vim_tests.py: -------------------------------------------------------------------------------- 1 | import os 2 | import unittest 3 | from inspect import getfile, currentframe 4 | 5 | import autoload.vim_python_test_runner as sut 6 | 7 | 8 | class RunPytestsInVimTests(unittest.TestCase): 9 | 10 | def test_create_command_to_run_current_file_with_pytests(self): 11 | path_to_current_file = "/tmp/project/tests/aTestFile.py" 12 | command_to_run = sut.get_command_to_run_current_file_with_pytests(path_to_current_file) 13 | self.assertEqual(":!pytest /tmp/project/tests/aTestFile.py", command_to_run) 14 | 15 | def test_create_command_to_run_current_file_with_pytests_writes_command_to_cache_file_when_successfully_called(self): 16 | path_to_current_file = "/tmp/project/tests/aTestFile.py" 17 | command_to_run = sut.get_command_to_run_current_file_with_pytests(path_to_current_file) 18 | last_command = sut.get_command_to_rerun_last_tests() 19 | self.assertEqual(command_to_run, last_command) 20 | 21 | def test_create_command_to_run_current_class_with_pytests(self): 22 | path_to_current_file = "/tmp/project/tests/aTestFile.py" 23 | current_line = 27 24 | current_buffer = self.build_buffer_helper() 25 | command_to_run = sut.get_command_to_run_current_class_with_pytests(path_to_current_file, current_line, current_buffer) 26 | self.assertEqual(":!pytest /tmp/project/tests/aTestFile.py::Example2", command_to_run) 27 | 28 | def test_create_command_to_run_current_class_with_pytests_writes_command_to_cache_file_when_successfully_called(self): 29 | path_to_current_file = "/tmp/project/tests/aTestFile.py" 30 | current_line = 27 31 | current_buffer = self.build_buffer_helper() 32 | command_to_run = sut.get_command_to_run_current_class_with_pytests(path_to_current_file, current_line, current_buffer) 33 | last_command = sut.get_command_to_rerun_last_tests() 34 | self.assertEqual(command_to_run, last_command) 35 | 36 | def test_create_command_to_run_current_method_with_pytests(self): 37 | path_to_current_file = "/tmp/project/tests/aTestFile.py" 38 | current_line = 44 39 | current_buffer = self.build_buffer_helper() 40 | command_to_run = sut.get_command_to_run_current_method_with_pytests(path_to_current_file, current_line, current_buffer) 41 | self.assertEqual(":!pytest /tmp/project/tests/aTestFile.py::Example3::double_dummy1", command_to_run) 42 | 43 | def test_create_command_to_run_current_method_with_pytests_writes_command_to_cache_file_when_successfully_called(self): 44 | path_to_current_file = "/tmp/project/tests/aTestFile.py" 45 | current_line = 44 46 | current_buffer = self.build_buffer_helper() 47 | command_to_run = sut.get_command_to_run_current_method_with_pytests(path_to_current_file, current_line, current_buffer) 48 | last_command = sut.get_command_to_rerun_last_tests() 49 | self.assertEqual(command_to_run, last_command) 50 | 51 | def test_create_command_to_run_current_method_with_pytests_when_not_in_a_class(self): 52 | path_to_current_file = "/tmp/project/tests/aTestFile.py" 53 | current_line = 5 54 | current_buffer = self.build_buffer_helper("classless_dummy_file.py") 55 | command_to_run = sut.get_command_to_run_current_base_method_with_pytests(path_to_current_file, current_line, current_buffer) 56 | self.assertEqual(":!pytest /tmp/project/tests/aTestFile.py::dummy_base_method1", command_to_run) 57 | 58 | def build_buffer_helper(self, dummy_file="dummy_test_file.py"): 59 | current_dir = os.path.dirname(os.path.abspath(getfile(currentframe()))) 60 | with open("{}/{}".format(current_dir, dummy_file), "r") as f: 61 | current_buffer = [] 62 | for line in f.readlines(): 63 | current_buffer.append(line) 64 | return current_buffer 65 | 66 | def get_cached_command(self): 67 | with open("/tmp/vim_python_test_runner_cache", "r") as f: 68 | return f.read() 69 | --------------------------------------------------------------------------------