-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add interactive test using pexpect #9
base: master
Are you sure you want to change the base?
Add interactive test using pexpect #9
Conversation
Codecov Report
@@ Coverage Diff @@
## master #9 +/- ##
==========================================
+ Coverage 73.65% 78.28% +4.63%
==========================================
Files 2 4 +2
Lines 410 456 +46
Branches 46 50 +4
==========================================
+ Hits 302 357 +55
+ Misses 98 83 -15
- Partials 10 16 +6
Continue to review full report at Codecov.
|
Awesome, started using pexpect for an integration test with pdbpp also: pdbpp/pdbpp#18 |
Added the missing pexpect dep to tox.ini. |
Apparently the libedit method fails on PyPy?! https://travis-ci.com/pdbpp/fancycompleter/jobs/203388229#L260 |
Interesting! I added the Unrelated note, before I forget: the output differed between Linux and OSX. Here's linux: 'complete_\x07\r\n complete_a complete_b complete_c \r\ncomplete_' And OSX: 'complete_complete_\x07\r\x1b[10G\r\n complete_a complete_b complete_c \r\n\r\x1b[Kcomplete_' |
btw: came up with the following diff when I've thought the py27 failure was due to a timeout/delay: diff --git a/testing/test_interactive.py b/testing/test_interactive.py
index 9e5f743..9c66f13 100644
--- a/testing/test_interactive.py
+++ b/testing/test_interactive.py
@@ -1,5 +1,4 @@
import os.path
-import time
import pexpect
@@ -16,27 +15,19 @@ def test_global_matches():
args = [FCOMPLETE_PATH]
args.extend(full_names)
- fcomplete = pexpect.spawn('python', args)
-
- try:
+ with pexpect.spawn('python', args, timeout=5) as fcomplete:
fcomplete.send(prefix)
- output = fcomplete.read_nonblocking(1000).decode('utf-8')
- assert output == prefix
+ fcomplete.expect_exact(prefix)
fcomplete.send('\t')
- fcomplete.read_nonblocking(1000).decode('utf-8')
+ # NOTE: on py27 it is:
+ # fcomplete.expect_exact('\tcomplete_\x07')
+ # But on py37 only:
+ fcomplete.expect_exact('\x07')
fcomplete.send('\t')
- time.sleep(0.1)
- output = fcomplete.read_nonblocking(1000).decode('utf-8')
- lines = output.split('\r\n')
-
- assert len(lines) == 3
- assert lines[2].endswith(prefix)
-
- assert all(full_name in lines[1] for full_name in full_names)
- completed_names = lines[1].strip().split(' ')
- assert set(completed_names) == set(full_names)
-
- finally:
- fcomplete.terminate(force=True)
+ fcomplete.expect_exact(
+ '\r\n'
+ ' complete_a complete_b complete_c '
+ '\r\ncomplete_'
+ ) While some of this is good, it is actually better to compare/assert the actual (whole) output like you do it. |
The py27 failure ("setupterm failed") reminded me of pypy/pyrepl#8. |
This might also be due to TERM - with pdbpp I'm setting TERM=xterm-256color always / explicitly: https://github.com/pdbpp/pdbpp/blob/c9318c31de813132c0564acd8831c8dda3fbc0d1/testing/conftest.py#L14-L22 |
AFAIK, curses reads info from a terminfo database to figure out how to interact with the terminal. Without The ncurses API docs (found through this SO answer) state an
The C source shows a little more detail tname = getenv("TERM");
if (tname == 0 || *tname == '\0') {
ret_error0(TGETENT_ERR, "TERM environment variable not set.\n");
}
#define TGETENT_ERR -1 /* an error occurred */ EDIT: btw, #define ret_error0(code, msg) if (errret) {\
*errret = code;\
returnCode(ERR);\
} else {\
fprintf(stderr, msg);\
exit(EXIT_FAILURE);\
} |
Didn't know about the contextmanager on |
Well, I dug in a bit deeper. tl;dr no solution, yet, but my eyes are on pyrepl. First, I tried all the possible values of TERM on my system w/ pypy/3. None of them seemed to print out nice, parseable, American-made Honestly, I hadn't used PyPy very much before, so it wasn't till I started printf debugging ('cause hooking up the PyCharm debugger to a pexpect child seemed like a rabbit hole for a different 1AM night) before I realized pyrepl is always used under PyPy — and shortly after it clicked: PyPy doesn't have a real readline; it just uses pyrepl for its readline. The same pyrepl I was avoiding with I was getting things like
(Though, it was the I wonder if there might be some way to massage pyrepl's readline into speaking normalspeak. Maybe chunking the characters written or read in some fashion would speak some sense into the thing. Maybe just interpreting the escape codes :O I have no idea what's gonna happen next, and I'm loving it. |
Would be great to pick this up / finish it. |
I spent some time messing about to find a way to test fancycompleter's interactive features. This PR has an example utilizing pexpect to spawn a cmd-module-based REPL backed by fancycompleter.
I tested it on Linux and OSX. It fails on Linux if
has_leopard_libedit
is forced toreturn False
.The pexpect dep was purely for convenience, and could likely be replaced with direct usage of
pty
.Hope it helps!