Passed
Push — test ( d838cf...cef4a5 )
by Tom
03:29
created

ExecTester::dealInvokeExpectation()   B

Complexity

Conditions 10
Paths 16

Size

Total Lines 59
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 38
nc 16
nop 5
dl 0
loc 59
rs 7.6666
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/* this file is part of pipelines */
4
5
namespace Ktomk\Pipelines\Cli;
6
7
use BadMethodCallException;
8
use Ktomk\Pipelines\TestCase;
9
use PHPUnit\Runner\BaseTestRunner;
10
use UnexpectedValueException;
11
12
/**
13
 * Emulate execution of command line utilities in tests
14
 */
15
class ExecTester extends Exec
16
{
17
    /**
18
     * @var TestCase
19
     */
20
    private $testCase;
21
22
    private $expects = array();
23
24
    private $debugMessages = array();
25
26
    /**
27
     * @param TestCase $testCase
28
     *
29
     * @return ExecTester
30
     */
31
    public static function create(TestCase $testCase)
32
    {
33
        return new self($testCase);
34
    }
35
36
    /**
37
     * ExecTester constructor.
38
     *
39
     * @param TestCase $testCase
40
     */
41
    public function __construct(TestCase $testCase)
42
    {
43
        $this->testCase = $testCase;
44
        parent::__construct(array($this, 'addDebugMessage'));
45
        parent::setActive(false);
46
    }
47
48
    /**
49
     * @throws \PHPUnit\Framework\AssertionFailedError
50
     */
51
    public function __destruct()
52
    {
53
        $testCase = $this->testCase;
54
55
        // if the test did not pass, keep the actual failure as there can
56
        // only be one.
57
        if (BaseTestRunner::STATUS_PASSED !== $testCase->getStatus()) {
58
            return;
59
        }
60
61
        $testCase->addToAssertionCount(1);
62
        if (count($this->expects)) {
63
            $testCase::fail(
64
                sprintf(
65
                    'Failed assertion that expected number of exec\'s were done (%d left)%s',
66
                    count($this->expects),
67
                    sprintf(":\n  - %s", implode("\n  - ", $this->expectMessages()))
68
                )
69
            );
70
        }
71
    }
72
73
    /**
74
     * @param string $method
75
     * @param string $command
76
     * @param callable|int|string $context (optional)
77
     * @param string $message (optional)
78
     *
79
     * @return $this
80
     */
81
    public function expect($method, $command, $context = 0, $message = null)
82
    {
83
        $this->expects[] = array($method, $command, $context, $message);
84
85
        return $this;
86
    }
87
88
    /**
89
     * @param $command
90
     * @param array $arguments
91
     * @param null $out
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $out is correct as it would always require null to be passed?
Loading history...
92
     * @param null $err
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $err is correct as it would always require null to be passed?
Loading history...
93
     *
94
     * @throws \PHPUnit\Framework\AssertionFailedError
95
     * @throws UnexpectedValueException
96
     *
97
     * @return $this|int
98
     */
99
    public function capture($command, array $arguments, &$out = null, &$err = null)
100
    {
101
        parent::capture($command, $arguments, $out, $err);
102
103
        return $this->dealInvokeExpectation(__FUNCTION__, $command, $arguments, $out, $err);
104
    }
105
106
    /**
107
     * @param string $command
108
     * @param array $arguments
109
     *
110
     * @throws \PHPUnit\Framework\AssertionFailedError
111
     * @throws UnexpectedValueException
112
     *
113
     * @return int|mixed
114
     */
115
    public function pass($command, array $arguments)
116
    {
117
        parent::pass($command, $arguments);
118
119
        return $this->dealInvokeExpectation(__FUNCTION__, $command, $arguments);
120
    }
121
122
    /**
123
     * @param bool $active
124
     *
125
     * @throws \BadMethodCallException
126
     */
127
    public function setActive($active)
128
    {
129
        if (false === (bool)$active) {
130
            return;
131
        }
132
133
        throw new BadMethodCallException(
134
            'This exec tester can not be used in tests that require setting it to active.'
135
        );
136
    }
137
138
    /**
139
     * @return array|string[]
140
     */
141
    public function getDebugMessages()
142
    {
143
        return $this->debugMessages;
144
    }
145
146
    /**
147
     * @param string $message
148
     */
149
    protected function addDebugMessage($message)
150
    {
151
        $this->debugMessages[] = $message;
152
    }
153
154
    /**
155
     * @return array
156
     */
157
    private function expectMessages()
158
    {
159
        $expects = $this->expects;
160
        $messages = array();
161
        foreach ($expects as $current) {
162
            list (
163
                $expectedMethod,
164
                $expectedCommand,
165
                $context,
166
                $message
167
                ) = $current;
168
            $messages[] = sprintf("%s: %s%s", $expectedMethod, $expectedCommand, $message ? " // ${message}" : '');
169
        }
170
171
        return $messages;
172
    }
173
174
    /**
175
     * @param string $method
176
     * @param string $command
177
     * @param array $arguments
178
     * @param null $out
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $out is correct as it would always require null to be passed?
Loading history...
179
     * @param null $err
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $err is correct as it would always require null to be passed?
Loading history...
180
     *
181
     * @throws UnexpectedValueException
182
     * @throws \PHPUnit\Framework\AssertionFailedError
183
     *
184
     * @return int|mixed
185
     */
186
    private function dealInvokeExpectation($method, $command, array $arguments, &$out = null, &$err = null)
187
    {
188
        $current = array_shift($this->expects);
189
        $testCase = $this->testCase;
190
        if (null === $current) {
191
            $testCase::fail(
192
                sprintf(
193
                    "Exec tester violation: %s() with command '%s' called with no more expectations",
194
                    $method,
195
                    $command
196
                )
197
            );
198
        }
199
200
        list (
201
            $expectedMethod,
202
            $expectedCommand,
203
            $context,
204
            $message
205
            ) = $current;
206
207
        $testCase::assertSame(
208
            $expectedMethod,
209
            $method,
210
            sprintf("Method on exec mismatch with command '%s'%s", $command, $message ? " // ${message}" : '')
211
        );
212
213
        if ('' !== $expectedCommand && '~' === $expectedCommand[0]) {
214
            $testCase::assertMatchesRegularExpression(
215
                $expectedCommand,
216
                $command,
217
                sprintf("Command on exec mismatch with method '%s'%s", $method, $message ? " // ${message}" : '')
218
            );
219
        } else {
220
            $testCase::assertSame(
221
                $expectedCommand,
222
                $command,
223
                sprintf("Command on exec mismatch with method '%s'%s", $method, $message ? " // ${message}" : '')
224
            );
225
        }
226
227
        if (is_int($context)) {
228
            return $context;
229
        }
230
231
        if (is_string($context)) {
232
            $out = $context;
233
234
            return 0;
235
        }
236
237
        if (is_callable($context)) {
238
            return call_user_func_array(
239
                $context,
240
                array($command, $arguments, &$out, &$err)
241
            );
242
        }
243
244
        throw new UnexpectedValueException('Invalid context');
245
    }
246
}
247