I'm using Pyperclip to put something into the clipboard and testing it with Pytest. I'm using GitHub actions for CI/CD that runs tox. Running pytest on my local system works just fine, but doing the same in tox fails because of the following display errors
@pytest.mark.parametrize(
("rs", "ip", "port", "expected"),
(("Something {} {}", "192", "1234", "Something 192 1234"),),
)
def test_rs_clipper(rs, ip, port, expected):
> provide_rs(rs, ip, port)
tests/test_langhandler.py:39:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.tox/python3.6/lib/python3.9/site-packages/rst/lang_handler.py:130: in provide_rs
pyperclip.copy(f"{rs.format(ip,port)}")
.tox/python3.6/lib/python3.9/site-packages/pyperclip/__init__.py:618: in lazy_load_stub_copy
return copy(text)
I'm assuming it's because of the virtual environment tox is creating. How can I simulate a display environment so at least the pyperclip functionality works?
Output for tox -rvv
setting PATH=/opt/rst/.tox/python3.6/bin:/opt/rst/venv/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/usr/share/games:/usr/local/sbin:/usr/sbin:/sbin:/root/.local/bin:/snap/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/usr/share/games:/usr/local/sbin:/usr/sbin:/sbin:/root/.local/bin:/snap/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
[1512278] /opt/rst$ /opt/rst/.tox/python3.6/bin/python -m pip freeze >.tox/python3.6/log/python3.6-0.log
python3.6 finish: envreport after 0.57 seconds
python3.6 installed: attrs==21.4.0,black==22.3.0,certifi==2021.10.8,charset-normalizer==2.0.12,click==8.1.2,commonmark==0.9.1,coverage==6.3.2,coverage-badge==1.1.0,distlib==0.3.4,filelock==3.6.0,flake8==4.0.1,idna==3.3,iniconfig==1.1.1,keyboard==0.13.5,mccabe==0.6.1,mypy==0.942,mypy-extensions==0.4.3,netifaces==0.10.9,packaging==21.3,pathspec==0.9.0,platformdirs==2.5.2,pluggy==1.0.0,py==1.11.0,pycodestyle==2.8.0,pyflakes==2.4.0,Pygments==2.12.0,pyngrok==5.1.0,pyparsing==3.0.8,pyperclip==1.8.0,pytest==7.1.1,pytest-cov==3.0.0,python-coveralls==2.9.3,PyYAML==6.0,requests==2.27.1,reverse-shell-tool @ file:///opt/rst/.tox/.tmp/package/1/reverse-shell-tool-1.0.2.tar.gz,rich==12.2.0,simple-term-menu==1.4.1,six==1.16.0,toml==0.10.2,tomli==2.0.1,tox==3.25.0,typing_extensions==4.2.0,urllib3==1.26.9,virtualenv==20.14.1
python3.6 start: run-test-pre
python3.6 run-test-pre: PYTHONHASHSEED='2092568237'
python3.6 finish: run-test-pre after 0.00 seconds
python3.6 start: run-test
python3.6 run-test: commands[0] | pytest --cov=/opt/rst/.tox/python3.6/tmp/src --basetemp=/opt/rst/.tox/python3.6/tmp
setting PATH=/opt/rst/.tox/python3.6/bin:/opt/rst/venv/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/usr/share/games:/usr/local/sbin:/usr/sbin:/sbin:/root/.local/bin:/snap/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/usr/share/games:/usr/local/sbin:/usr/sbin:/sbin:/root/.local/bin:/snap/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
[1512279] /opt/rst$ /opt/rst/.tox/python3.6/bin/pytest --cov=/opt/rst/.tox/python3.6/tmp/src --basetemp=/opt/rst/.tox/python3.6/tmp
============================================================== test session starts ===============================================================
platform linux -- Python 3.9.2, pytest-7.1.1, pluggy-1.0.0
cachedir: .tox/python3.6/.pytest_cache
rootdir: /opt/rst, configfile: pyproject.toml, testpaths: tests
plugins: cov-3.0.0
collected 2 items
tests/test_langhandler.py .F [100%]/opt/rst/.tox/python3.6/lib/python3.9/site-packages/coverage/inorout.py:519: CoverageWarning: Module /opt/rst/.tox/python3.6/tmp/src was never imported. (module-not-imported)
self.warn(f"Module {pkg} was never imported.", slug="module-not-imported")
/opt/rst/.tox/python3.6/lib/python3.9/site-packages/coverage/control.py:793: CoverageWarning: No data was collected. (no-data-collected)
self._warn("No data was collected.", slug="no-data-collected")
WARNING: Failed to generate report: No data to report.
/opt/rst/.tox/python3.6/lib/python3.9/site-packages/pytest_cov/plugin.py:294: CovReportWarning: Failed to generate report: No data to report.
self.cov_controller.finish()
==================================================================== FAILURES ====================================================================
__________________________________________ test_rs_clipper[Something {} {}-192-1234-Something 192 1234] __________________________________________
rs = 'Something {} {}', ip = '192', port = '1234', expected = 'Something 192 1234'
@pytest.mark.parametrize(
("rs", "ip", "port", "expected"),
(("Something {} {}", "192", "1234", "Something 192 1234"),),
)
def test_rs_clipper(rs, ip, port, expected):
> provide_rs(rs, ip, port)
tests/test_langhandler.py:39:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.tox/python3.6/lib/python3.9/site-packages/rst/lang_handler.py:130: in provide_rs
pyperclip.copy(f"{rs.format(ip,port)}")
.tox/python3.6/lib/python3.9/site-packages/pyperclip/__init__.py:618: in lazy_load_stub_copy
return copy(text)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <pyperclip.init_no_clipboard.<locals>.ClipboardUnavailable object at 0x7f35938c1970>, args = ('Something 192 1234',), kwargs = {}
def __call__(self, *args, **kwargs):
> raise PyperclipException(EXCEPT_MSG)
E pyperclip.PyperclipException:
E Pyperclip could not find a copy/paste mechanism for your system.
E For more information, please visit https://pyperclip.readthedocs.io/en/latest/index.html#not-implemented-error
.tox/python3.6/lib/python3.9/site-packages/pyperclip/__init__.py:303: PyperclipException
----------- coverage: platform linux, python 3.9.2-final-0 -----------
============================================================ short test summary info =============================================================
FAILED tests/test_langhandler.py::test_rs_clipper[Something {} {}-192-1234-Something 192 1234] - pyperclip.PyperclipException:
========================================================== 1 failed, 1 passed in 0.19s ===========================================================
ERROR: InvocationError for command /opt/rst/.tox/python3.6/bin/pytest --cov=/opt/rst/.tox/python3.6/tmp/src --basetemp=/opt/rst/.tox/python3.6/tmp (exited with code 1)
python3.6 finish: run-test after 0.59 seconds
python3.6 start: run-test-post
python3.6 finish: run-test-post after 0.00 seconds
I haven't used pyperclip in CI/CD before, so I might be totally wrong, but my guess is that you need to start an X server within a virtual frame buffer. Here's a link to one of my projects that does this, but I've copied the important part below:
Basically, I just use GabrielBB/xvfb-action and it sets everything up for me. Again, I'm not sure that this will work for you, but I figured I'd put it out there just in case.
Edit: Starting an X server is just the first step, you also need to provide pyperclip with a way to access the clipboard, i.e. by installing
xsel,xclip,gtk, orqt. See this stack overflow post for more details, but basically you need to add something like this to your CI workflow: