Răsfoiți Sursa

Try to write integration test which installs and runs a simple program

Thomas Kluyver 5 ani în urmă
părinte
comite
58aa7e0b39

+ 0 - 28
nsist/tests/console_example/guessnumber.py

@@ -1,28 +0,0 @@
-"""A fun number guessing game!"""
-
-import random
-
-def main():
-    number = random.randint(1, 100)
-    guesses = 0
-
-    print("I'm thinking of a number, between 1 and 100. Can you guess what it is?")
-    while True:
-        guesses += 1
-        guess = input('= ')
-        try:
-            guess = int(guess)
-        except ValueError:
-            print("Base 10 integers only, please.")
-            continue
-
-        if guess > number:
-            print("Too high!")
-        elif guess <  number:
-            print("Too low!")
-        else:
-            print("That's right, {}. You got it in {} guesses.".format(number, guesses))
-            break
-
-    print()
-    input("Press enter to quit.")

+ 5 - 5
nsist/tests/console_example/installer.cfg

@@ -1,7 +1,7 @@
 [Application]
-name=Guess the Number
+name=Sample printer
 version=1.0
-entry_point=guessnumber:main
+entry_point=sample_printer:main
 # We need to set this to get a console:
 console=true
 
@@ -11,9 +11,9 @@ bitness=64
 format=bundled
 
 [Include]
-packages=guessnumber
+packages=sample_printer
 
 # This optional section adds a command which can be run from the Windows
 # command prompt.
-[Command guessnumber]
-entry_point=guessnumber:main
+[Command pynsist-test-print]
+entry_point=sample_printer:main

+ 17 - 0
nsist/tests/console_example/sample_printer/__init__.py

@@ -0,0 +1,17 @@
+import json
+import os.path
+import sys
+
+def main():
+    data_file = os.path.join(os.path.dirname(__file__), 'data.txt')
+    with open(data_file, 'r', encoding='utf-8') as f:
+        data_from_file = f.read().strip()
+
+    info = {
+        'py_executable': sys.executable,
+        'py_version': sys.version,
+        'data_file_path': data_file,
+        'data_file_content': data_from_file,
+    }
+
+    print(json.dumps(info, indent=True))

+ 1 - 0
nsist/tests/console_example/sample_printer/data.txt

@@ -0,0 +1 @@
+newt

+ 58 - 18
nsist/tests/test_main.py

@@ -1,18 +1,27 @@
 import io
+import json
 from pathlib import Path
+import pytest
 import re
 import responses
-from shutil import copy
-from testpath import MockCommand, modified_env, assert_isfile, assert_isdir
-from testpath.tempdir import TemporaryWorkingDirectory
+from shutil import copytree
+from subprocess import run, PIPE
+import sys
+from testpath import MockCommand, assert_isfile, assert_isdir
 from zipfile import ZipFile
 
 from nsist import main
 from nsist.util import CACHE_ENV_VAR
-from .utils import test_dir
+from .utils import test_dir, only_on_windows
 
 example_dir = Path(test_dir, 'console_example')
 
+@pytest.fixture()
+def console_eg_copy(tmp_path):
+    dst = tmp_path / 'example'
+    copytree(str(example_dir), str(dst))
+    return dst
+
 def respond_python_zip(req):
     buf = io.BytesIO()
     with ZipFile(buf, 'w') as zf:
@@ -20,25 +29,56 @@ def respond_python_zip(req):
     return 200, {}, buf.getvalue()
 
 @responses.activate
-def test_console_example():
+def test_console_example(tmp_path, console_eg_copy, monkeypatch):
     responses.add_callback('GET', re.compile(r'https://www.python.org/ftp/.*'),
         callback=respond_python_zip, content_type='application/zip',
     )
 
-    with TemporaryWorkingDirectory() as td:
-        for src in example_dir.iterdir():
-            copy(str(src), td)
+    monkeypatch.chdir(console_eg_copy)
+    monkeypatch.setenv(CACHE_ENV_VAR, str(tmp_path / 'cache'))
+
+    with MockCommand('makensis') as makensis:
+        ec = main(['installer.cfg'])
+
+    assert ec == 0
+    assert makensis.get_calls()[0]['argv'][1].endswith('installer.nsi')
+
+    build_dir = console_eg_copy / 'build' / 'nsis'
+    assert_isdir(build_dir)
+    assert_isfile(build_dir / 'Python' / 'python.exe')
+    assert_isfile(build_dir / 'pkgs' / 'sample_printer' / '__init__.py')
+    assert_isfile(build_dir / 'Sample_printer.launch.py')
+
+# To exclude tests requiring network on an unplugged machine, use: pytest -m "not network"
+
+@only_on_windows
+@pytest.mark.network
+def test_installer(console_eg_copy, tmp_path):
+    # Create installer
+    run(
+        [sys.executable, '-m', 'nsist', 'installer.cfg'],
+        cwd=console_eg_copy,
+        check=True,
+    )
+
+    installer = Path(console_eg_copy, 'build', 'nsis', 'Guess_the_Number_1.0.exe')
+    inst_dir = tmp_path / 'inst'
+
+    # Run installer
+    run([installer, '/S', '/D={}'.format(inst_dir)], check=True)
+    inst_python = inst_dir / 'Python' / 'python.exe'
+    inst_launch_script = inst_dir / 'Sample_printer.launch.py'
 
+    assert_isfile(inst_python)
+    assert_isfile(inst_launch_script)
+    assert_isfile(inst_dir / 'pkgs' / 'sample_printer' / '__init__.py')
 
-        with modified_env({CACHE_ENV_VAR: td}), \
-             MockCommand('makensis') as makensis:
-            ec = main(['installer.cfg'])
 
-        assert ec == 0
-        assert makensis.get_calls()[0]['argv'][1].endswith('installer.nsi')
+    # Run installed program
+    res = run([inst_python, inst_launch_script], check=True, stdout=PIPE)
+    json_res = json.loads(res.stdout)
 
-        build_dir = Path(td, 'build', 'nsis')
-        assert_isdir(build_dir)
-        assert_isfile(build_dir / 'Python' / 'python.exe')
-        assert_isfile(build_dir / 'pkgs' / 'guessnumber.py')
-        assert_isfile(build_dir / 'Guess_the_Number.launch.py')
+    assert json_res['py_executable'] == str(inst_python)
+    assert json_res['py_version'].startswith('3.6.3')  # Set in installer.cfg
+    assert json_res['data_file_path'].endswith('data.txt')
+    assert json_res['data_file_content'] == 'newt'