<gh_stars>1-10
import os
import subprocess

import mock
from testify import setup_teardown, TestCase, test_program
from testify.assertions import assert_equal, assert_raises, assert_in
from optparse import OptionParser


class OptionParserErrorException(Exception):
    pass


class ParseTestRunnerCommandLineArgsTest(TestCase):
    @setup_teardown
    def patch_OptionParser_error(self):
        def new_error(*args, **kwargs):
            raise OptionParserErrorException(*args, **kwargs)
        with mock.patch.object(OptionParser, 'error', side_effect=new_error):
            yield

    def test__parse_test_runner_command_line_module_method_overrides_empty_input(self):
        """Make sure _parse_test_runner_command_line_module_method_overrides returns something sensible if you pass it an empty list of arguments."""
        assert_equal(test_program._parse_test_runner_command_line_module_method_overrides([]), (None, {}))

    def test_parse_test_runner_command_line_args_rerun_test_file(self):
        """Make sure that when --rerun-test-file is passed, parse_test_runner_command_line_args doesn't complain about a missing test path."""
        test_program.parse_test_runner_command_line_args([], ['--rerun-test-file', '-'])

    def test_parse_test_runner_command_line_args_connect(self):
        """Make sure that when --connect is passed, parse_test_runner_command_line_args doesn't complain about a missing test path."""
        test_program.parse_test_runner_command_line_args([], ['--connect', 'localhost:65537'])

    def test_parse_test_runner_command_line_args_replay_json_inline(self):
        """Make sure that when --replay-json-inline is passed, parse_test_runner_command_line_args doesn't complain about a missing test path."""
        test_program.parse_test_runner_command_line_args([], ['--replay-json-inline', '{something that obviously isnt json}'])

    def test_parse_test_runner_command_line_args_replay_json(self):
        """Make sure that when --replay-json-inline is passed, parse_test_runner_command_line_args doesn't complain about a missing test path."""
        test_program.parse_test_runner_command_line_args([], ['--replay-json', 'somejsonfile.txt'])

    def test_parse_test_runner_command_line_args_no_test_path(self):
        """Make sure that if no options and no arguments are passed, parse_test_runner_command_line_args DOES complain about a missing test path."""
        with assert_raises(OptionParserErrorException):
            test_program.parse_test_runner_command_line_args([], [])


def test_call(command):
    proc = subprocess.Popen(command, stdout=subprocess.PIPE)
    stdout, stderr = proc.communicate()
    if proc.returncode:
        raise subprocess.CalledProcessError(proc.returncode, command)
    return stdout.strip()


class TestifyRunAcceptanceTestCase(TestCase):

    expected_list = (
        'testing_suite.example_test ExampleTestCase.test_one\n'
        'testing_suite.example_test ExampleTestCase.test_two\n'
        'testing_suite.example_test SecondTestCase.test_one'
    )

    expected_tests = 'PASSED.  3 tests'

    def test_run_testify_from_bin_list_tests(self):
        output = test_call(['bin/testify', '--list-tests', 'testing_suite'])
        assert_equal(output, self.expected_list)

    def test_run_testify_as_module_list_tests(self):
        output = test_call([
                'python', '-m', 'testify.test_program',
                '--list-tests', 'testing_suite'])
        assert_equal(output, self.expected_list)

    def test_run_testify_from_bin(self):
        output = test_call(['bin/testify', 'testing_suite', '-v'])
        assert_in(self.expected_tests, output)

    def test_run_testify_test_module(self):
        output = test_call(['python', '-m', 'testing_suite.example_test', '-v'])
        assert_in(self.expected_tests, output)

    def test_run_testify_test_file(self):
        output = test_call(['python', 'testing_suite/example_test.py', '-v'])
        assert_in(self.expected_tests, output)

    def test_run_testify_test_file_class(self):
        output = test_call([
                'python', 'testing_suite/example_test.py', '-v',
                'ExampleTestCase'])
        assert_in('PASSED.  2 tests', output)

    def test_run_testify_test_file_class_and_method(self):
        output = test_call([
                'python', 'testing_suite/example_test.py', '-v',
                'ExampleTestCase.test_one'])
        assert_in('PASSED.  1 test', output)

    def test_run_testify_with_failure(self):
        assert_raises(
                subprocess.CalledProcessError,
                test_call,
                ['python', 'testing_suite/example_test.py', 'DoesNotExist'])


class TestClientServerReturnCode(TestCase):
    def test_client_returns_zero_on_success(self):
        server_process = subprocess.Popen(
            [
                'python', '-m', 'testify.test_program',
                'testing_suite.example_test',
                '--serve', '9001',
            ],
            stdout=open(os.devnull, 'w'),
            stderr=open(os.devnull, 'w'),
        )
        # test_call has the side-effect of asserting the return code is 0
        ret = test_call([
            'python', '-m', 'testify.test_program',
            '--connect', 'localhost:9001',
        ])
        assert_in('PASSED', ret)
        assert_equal(server_process.wait(), 0)

    def test_client_returns_nonzero_on_failure(self):
        server_process = subprocess.Popen(
            [
                'python', '-m', 'testify.test_program',
                'test.failing_test',
                '--serve', '9001',
            ],
            stdout=open(os.devnull, 'w'),
            stderr=open(os.devnull, 'w'),
        )
        # Need two clients in order to finish running tests
        client_1 = subprocess.Popen(
            [
                'python', '-m', 'testify.test_program',
                '--connect', 'localhost:9001',
            ],
            stdout=open(os.devnull, 'w'),
            stderr=open(os.devnull, 'w'),
        )
        client_2 = subprocess.Popen(
            [
                'python', '-m', 'testify.test_program',
                '--connect', 'localhost:9001',
            ],
            stdout=open(os.devnull, 'w'),
            stderr=open(os.devnull, 'w'),
        )
        assert_equal(client_1.wait(), 1)
        assert_equal(client_2.wait(), 1)
        assert_equal(server_process.wait(), 1)
            
