mirror of
				https://github.com/nvbn/thefuck.git
				synced 2025-10-31 15:12:20 +00:00 
			
		
		
		
	#N/A Add docker-based functional tests
This commit is contained in:
		| @@ -292,11 +292,17 @@ pip install -r requirements.txt | |||||||
| python setup.py develop | python setup.py develop | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| Run tests: | Run unit tests: | ||||||
|  |  | ||||||
| ```bash | ```bash | ||||||
| py.test | py.test | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
|  | Run unit and functional tests (requires docker): | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | FUNCTIONAL=true py.test | ||||||
|  | ``` | ||||||
|  |  | ||||||
| ## License MIT | ## License MIT | ||||||
| Project License can be found [here](LICENSE.md). | Project License can be found [here](LICENSE.md). | ||||||
|   | |||||||
| @@ -3,3 +3,4 @@ mock | |||||||
| pytest-mock | pytest-mock | ||||||
| wheel | wheel | ||||||
| setuptools>=17.1 | setuptools>=17.1 | ||||||
|  | pexpect | ||||||
|   | |||||||
							
								
								
									
										0
									
								
								tests/functional/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								tests/functional/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										49
									
								
								tests/functional/test_bash.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								tests/functional/test_bash.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | |||||||
|  | import pytest | ||||||
|  | from tests.functional.utils import build_container, spawn, run, read_until, \ | ||||||
|  |     root, functional | ||||||
|  |  | ||||||
|  | containers = [('thefuck/ubuntu-python3-bash', ''' | ||||||
|  | FROM ubuntu:latest | ||||||
|  | RUN apt-get update | ||||||
|  | RUN apt-get install -yy python3 python3-pip python3-dev | ||||||
|  | RUN pip3 install -U setuptools | ||||||
|  | RUN ln -s /usr/bin/pip3 /usr/bin/pip | ||||||
|  | RUN echo "PS1='$ '" > /root/.bashrc | ||||||
|  | CMD ["/bin/bash"] | ||||||
|  | '''), | ||||||
|  |               ('thefuck/ubuntu-python2-bash', ''' | ||||||
|  | FROM ubuntu:latest | ||||||
|  | RUN apt-get update | ||||||
|  | RUN apt-get install -yy python python-pip python-dev | ||||||
|  | RUN pip2 install -U pip setuptools | ||||||
|  | RUN echo "PS1='$ '" > /root/.bashrc | ||||||
|  | CMD ["/bin/bash"] | ||||||
|  | ''')] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @functional | ||||||
|  | @pytest.mark.parametrize('tag, dockerfile', containers) | ||||||
|  | def test_with_confirmation(tag, dockerfile): | ||||||
|  |     build_container(tag, dockerfile) | ||||||
|  |     with spawn(tag, '{}:/src'.format(root), | ||||||
|  |                ['cd /src', 'pip install .', 'eval $(thefuck-alias)']) as proc: | ||||||
|  |         run(proc, 'ehco test') | ||||||
|  |         proc.sendline('fuck') | ||||||
|  |         read_until(proc, '[') | ||||||
|  |         proc.send('\n') | ||||||
|  |         out = read_until(proc) | ||||||
|  |         assert out.split('\n')[-2] == 'test\r\r' | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @functional | ||||||
|  | @pytest.mark.parametrize('tag, dockerfile', containers) | ||||||
|  | def test_without_confirmation(tag, dockerfile): | ||||||
|  |     build_container(tag, dockerfile) | ||||||
|  |     with spawn(tag, '{}:/src'.format(root), | ||||||
|  |                ['cd /src', 'pip install .', | ||||||
|  |                 'export THEFUCK_REQUIRE_CONFIRMATION=false', | ||||||
|  |                 'eval $(thefuck-alias)']) as proc: | ||||||
|  |         run(proc, 'ehco test') | ||||||
|  |         run(proc, 'fuck') | ||||||
|  |         out = read_until(proc) | ||||||
|  |         assert out.split('\n')[-2] == 'test\r\r' | ||||||
							
								
								
									
										50
									
								
								tests/functional/test_zsh.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								tests/functional/test_zsh.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | |||||||
|  | import pytest | ||||||
|  | from tests.functional.utils import build_container, spawn, run, read_until, \ | ||||||
|  |     root, functional | ||||||
|  |  | ||||||
|  | containers = [('thefuck/ubuntu-python3-zsh', ''' | ||||||
|  | FROM ubuntu:latest | ||||||
|  | RUN apt-get update | ||||||
|  | RUN apt-get install -yy python3 python3-pip python3-dev zsh | ||||||
|  | RUN pip3 install -U setuptools | ||||||
|  | RUN ln -s /usr/bin/pip3 /usr/bin/pip | ||||||
|  | RUN echo "PS1='\\n$ '" > /root/.zshrc | ||||||
|  | CMD ["/bin/zsh"] | ||||||
|  | '''), | ||||||
|  |               ('thefuck/ubuntu-python2-zsh', ''' | ||||||
|  | FROM ubuntu:latest | ||||||
|  | RUN apt-get update | ||||||
|  | RUN apt-get install -yy python python-pip python-dev zsh | ||||||
|  | RUN pip2 install -U pip setuptools | ||||||
|  | RUN echo "PS1='\\n$ '" > /root/.zshrc | ||||||
|  | CMD ["/bin/zsh"] | ||||||
|  | ''')] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @functional | ||||||
|  | @pytest.mark.parametrize('tag, dockerfile', containers) | ||||||
|  | def test_with_confirmation(tag, dockerfile): | ||||||
|  |     build_container(tag, dockerfile) | ||||||
|  |     with spawn(tag, '{}:/src'.format(root), | ||||||
|  |                ['cd /src', 'pip install .', 'eval $(thefuck-alias)']) as proc: | ||||||
|  |         run(proc, 'ehco "\ntest"') | ||||||
|  |         proc.sendline('fuck') | ||||||
|  |         read_until(proc, '[') | ||||||
|  |         proc.send('\n') | ||||||
|  |         read_until(proc) | ||||||
|  |         out = read_until(proc) | ||||||
|  |         assert out.split('\n')[-3] == 'test\r\r' | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @functional | ||||||
|  | @pytest.mark.parametrize('tag, dockerfile', containers) | ||||||
|  | def test_without_confirmation(tag, dockerfile): | ||||||
|  |     build_container(tag, dockerfile) | ||||||
|  |     with spawn(tag, '{}:/src'.format(root), | ||||||
|  |                ['cd /src', 'pip install .', | ||||||
|  |                 'export THEFUCK_REQUIRE_CONFIRMATION=false', | ||||||
|  |                 'eval $(thefuck-alias)']) as proc: | ||||||
|  |         run(proc, 'ehco "\ntest"') | ||||||
|  |         run(proc, 'fuck') | ||||||
|  |         out = read_until(proc) | ||||||
|  |         assert out.split('\n')[-3] == 'test\r\r' | ||||||
							
								
								
									
										57
									
								
								tests/functional/utils.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								tests/functional/utils.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | |||||||
|  | import sys | ||||||
|  | import os | ||||||
|  | import pytest | ||||||
|  | from contextlib import contextmanager | ||||||
|  | import pexpect | ||||||
|  | import subprocess | ||||||
|  | import shutil | ||||||
|  | from tempfile import mkdtemp | ||||||
|  | from pathlib import Path | ||||||
|  |  | ||||||
|  | root = str(Path(__file__).parent.parent.parent.resolve()) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def build_container(tag, dockerfile): | ||||||
|  |     tmpdir = mkdtemp() | ||||||
|  |     with Path(tmpdir).joinpath('Dockerfile').open('w') as file: | ||||||
|  |         file.write(dockerfile) | ||||||
|  |     if subprocess.call(['docker', 'build', '--tag={}'.format(tag), tmpdir]) != 0: | ||||||
|  |         raise Exception("Can't build container") | ||||||
|  |     shutil.rmtree(tmpdir) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def read_until(proc, string='\n$ '): | ||||||
|  |     text = '' | ||||||
|  |     while True: | ||||||
|  |         text += proc.read(1) | ||||||
|  |         sys.stdout.write(text[-1]) | ||||||
|  |         sys.stdout.flush() | ||||||
|  |         if text.endswith(string): | ||||||
|  |             return text | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def run(proc, cmd): | ||||||
|  |     proc.sendline(cmd) | ||||||
|  |     return read_until(proc) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @contextmanager | ||||||
|  | def spawn(tag, volume, prepare=None): | ||||||
|  |     if prepare is None: | ||||||
|  |         prepare = [] | ||||||
|  |  | ||||||
|  |     proc = pexpect.spawnu( | ||||||
|  |         'docker run --volume {} --tty=true --interactive=true {}'.format( | ||||||
|  |             volume, tag)) | ||||||
|  |  | ||||||
|  |     try: | ||||||
|  |         for line in prepare: | ||||||
|  |             run(proc, line) | ||||||
|  |         yield proc | ||||||
|  |     finally: | ||||||
|  |         proc.terminate() | ||||||
|  |  | ||||||
|  |  | ||||||
|  | functional = pytest.mark.skipif( | ||||||
|  |     not os.environ.get('FUNCTIONAL'), | ||||||
|  |     reason='Functional tests are disabled by default.') | ||||||
		Reference in New Issue
	
	Block a user