Closed RonanMacF closed 3 years ago
To expand on the above point, my use case is as follows. I am using python2 and the test passes control off to a different process during execution, this means that the client is only attached to the first thread and then the test executes without hitting any of the other breakpoints. Ideally I would like to be able to call a pdb.set_trace()
or debugpy.breakpoint()
when the part of the code I am interested in is being executed so it will be attached to the right thread. I don't think :Ultest
will run this file as it wont see it as a testcase, instead it will be ran by direct execution from the commandline.
I also had difficulty replicating the gif from the README. It is a small file and looks basic but I was unable to attach and Ultest marked the test as passing, see asciicinema.
OK before I address the initial request, that asciinema definitely looks like something is wrong. Could you tell me more about your vim-test configuration and also attach a log of ultest. I replicated that file and have the expected behaviour myself. My only config is
let test#python#runner = "pytest"
Ah I only had the DAP python configuration done. Showing pytest makes it fail alright. It immediately shows a fail sign instead of a running sign and I am unable to attach to it still, but the floating window is showing some information and I see the test is ran using python2.7 so maybe if I get it to run with py3 it will resolve that issue. rec
logs probably not useful now but just in case
17:50:40 | INFO | MainThread | logging.py:create_logger:98 | Logger created
17:50:40 | DEBUG | MainThread | __init__.py:__init__:43 | Handler created
17:50:40 | DEBUG | Thread-1 | __init__.py:_handle_coroutine:58 | Starting job with group update_positions
17:50:40 | INFO | Thread-1 | tracker.py:_async_update:55 | Updating positions in test_a.py
17:50:40 | DEBUG | Thread-1 | file.py:parse_file_structure:25 | Converted pattern {'test': ['\\v^\\s*%(async )?def (test_\\w+)'], 'namespace': ['\\v^\\s*class (\\w+)']} to {'test': [re.compile('^\\s*(?:async )?def (test_\\w+)')], 'namespace': [re.compile('^\\s*class (\\w+)')]}
17:50:40 | DEBUG | Thread-1 | tracker.py:_async_update:82 | New test test_a.py found in test_a.py
17:50:40 | DEBUG | Thread-1 | tracker.py:_async_update:82 | New test test_b6425322089350344128 found in test_a.py
17:50:40 | DEBUG | Thread-1 | tracker.py:_remove_old_positions:125 | No tests removed
17:50:40 | DEBUG | Thread-1 | __init__.py:_handle_coroutine:78 | Finished job with group update_positions
17:50:43 | INFO | MainThread | __init__.py:run_nearest:125 | Running nearest test in test_a.py at line 0
17:50:43 | DEBUG | MainThread | __init__.py:_register_started:281 | Registering test_a.py as started
17:50:43 | DEBUG | MainThread | __init__.py:_register_started:281 | Registering test_b6425322089350344128 as started
17:50:43 | DEBUG | Thread-1 | __init__.py:_handle_coroutine:58 | Starting job with group test_a.py
17:50:43 | DEBUG | Thread-1 | processes.py:run:50 | Starting test process test_a.py with command ['pytest', 'test_a.py'], cwd = None, env = None
17:50:44 | DEBUG | Thread-1 | processes.py:run:76 | Process test_a.py complete with exit code: 1
17:50:44 | DEBUG | Thread-1 | __init__.py:_register_result:292 | Registering test_a.py as exited with result {"id": "test_a.py", "file": "test_a.py", "code": 1, "output": "/var/folders/x4/wv98pc6d38n0ykn769h63jjw0000gn/T/ultesttbsavbcd/test_a_py/test_a_py_out"}
17:50:44 | DEBUG | Thread-1 | __init__.py:_register_result:292 | Registering test_b6425322089350344128 as exited with result {"id": "test_b6425322089350344128", "file": "test_a.py", "code": 1, "output": "/var/folders/x4/wv98pc6d38n0ykn769h63jjw0000gn/T/ultesttbsavbcd/test_a_py/test_a_py_out"}
17:50:44 | DEBUG | Thread-1 | __init__.py:_handle_coroutine:78 | Finished job with group test_a.py
17:50:44 | DEBUG | MainThread | __init__.py:_present_output:109 | Showing test_a.py output
17:50:44 | DEBUG | MainThread | __init__.py:_present_output:109 | Showing test_b6425322089350344128 output
17:50:50 | INFO | MainThread | __init__.py:get_attach_script:206 | Creating script to attach to process test_b6425322089350344128
17:50:50 | INFO | MainThread | __init__.py:get_attach_script:206 | Creating script to attach to process test_a.py
Yep that's a local issue you can see that pytest is being called correctly.
17:50:43 | DEBUG | Thread-1 | processes.py:run:50 | Starting test process test_a.py with command ['pytest', 'test_a.py'], cwd = None, env = None
If you want to use python 2 you'll need to replace breakpoint()
with pdb.set_trace()
On your initial request, this should be totally doable. However it's not vim-ultest you should be looking at, but rather vim-test. You can define custom runners to implement whatever logic you like for running tests as long as they implement the correct interface. See the docs here https://github.com/vim-test/vim-test/#extending. I'd also say to check out the pytest runner as it'll be a good place to start from. https://github.com/vim-test/vim-test/blob/master/autoload/test/python/pytest.vim.
Once you've defined the runner, it should just work with vim-ultest!
The private function call ultest#handler#get_nearest_test(line("."), expand("%:."), v:false)
is slightly misleading as the file itself counts as a position. If no test is found then the file is treated as the position. This is how the Ultest
command works. So therefore the attach command should already attach to the file's process if there is one.
Cheers making own runner doesn't look too bad, will look into it and see if I can get it attaching, thanks!
Looking at the code I see
command! UltestAttach call ultest#output#attach(ultest#handler#get_nearest_test(line("."), expand("%:."), v:false))
This gives me the impression that if no nearest test is found then no process will be attached to. What would be nice if given the following fileIf we ran the
:UltestAttach
command, it would first check for nearest test and try to attach. If no test is found as a fallback it will try to find the (newest?) process which contains the file name and tries to attach to that.Would something like this be feasible?