Skip to content
This repository has been archived by the owner on Jan 31, 2020. It is now read-only.

Fix StaticValidator::execute tests and behavior #26

Closed
wants to merge 5 commits into from

Conversation

weierophinney
Copy link
Member

This is an attempt to address #16.

Previously, the tests were incorrectly passing a non-associative array of options to execute(), which implied that they would be passed as constructor arguments, which was not the case. In this particular case, there was a false positive, as the value being validated was valid for the default values present in the instance.

This patch removes that assertion, and splits the test into two, one for validating properly formed calls to the method with options as an associative array, and one for calling it with non-associative options. In the second, the test asserts that an InvalidArgumentException is expected.

The patch is a potential BC break. However, passing a non-associative array of arguments had unexpected behavior previously, and relying on that behavior would result in application bugs. The change to raise an exception ensures consistent behavior.

Previously, the tests were incorrectly passing a non-associative array
of options to `execute()`, which implied that they would be passed as
constructor arguments, which was not the case. In this particular
case, there was a false positive, as the value being validated was
valid for the default values present in the instance.

This patch removes that assertion, and splits the test into two, one for
validating properly formed calls to the method with options as an associative
array, and one for calling it with non-associative options. In the second, the
test asserts that an `InvalidArgumentException` is expected.
The ValidatorChainTest suite duplicated StaticValidator tests -
particularly the faulty ones this patch is attempting to fix.
@@ -52,6 +52,12 @@ public static function getPluginManager()
*/
public static function execute($value, $classBaseName, array $args = [])
{
if ($args && array_values($args) === $args) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this check to be done in the PluginManager?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forgive this

@Maks3w
Copy link
Member

Maks3w commented Jul 21, 2015

I see three cases here:

  • Constructor uses func_get_args
  • $args is used for constructor arguments so could be a bidimensional array passing the options as first argument
    `[ [ options ] ]
  • $args is the array options accidentaly used as constructor arguments list

Because argument name is $args which means arguments list I think the current implementation is the correct. The intention of provide a constructor argument list.

Provide a constructor argument list allow to instantiate constructors with different constructor signatures and not only the ones based in AbstractValidator.

My opinion is not merge and won't fix.

@Maks3w
Copy link
Member

Maks3w commented Jul 21, 2015

I've forwarded my comment to the issue for to have a single thread.

@weierophinney
Copy link
Member Author

Constructor uses func_get_args

This one is a moot point; the plugin manager always passes arguments (options) as an array, never using variadics.

$args is used for constructor arguments so could be a bidimensional array passing the options as first argument [ [ options ] ]

This does not occur currently.

$args is the array options accidentaly used as constructor arguments list

$args is passed as the $options argument to the plugin manager instance, and $options, if present, is always passed as the sole argument to the plugin constructor. The specified use case when we designed this was precisely for passing an associative array (or array-like object) of options to the plugin, to allow setting its initial state.

Which completely invalidates this assertion:

Because argument name is $args which means arguments list I think the current implementation is the correct. The intention of provide a constructor argument list.

That was never the intention. If it were, I would have coded the AbstractPluginManager differently. This is simply a case of (a) misnamed argument, and (b) incorrect initial tests. Somebody essentially discovered that we were not covering an edge case properly.

With that knowledge, please re-review.

- Adds an `@throws` annotation to `execute()`
- Renames `$args` to `$options` to better indicate that it is passed as
  the `$options` argument to `ValidatorPluginManager::get()`.
@@ -47,14 +47,22 @@ public static function getPluginManager()
/**
* @param mixed $value
* @param string $classBaseName
* @param array $args OPTIONAL
* @param array $optons OPTIONAL options to pass to the validator constructor;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • typo s/optons/options
  • Include "as first argument". "associative array of options for to inject in the first argument of the validator constructor"

*/
public function testExecuteValidWithParameters($value, $validator, $options, $assertion)
{
$this->$assertion(StaticValidator::execute($value, $validator, $options));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lately I prefer asser the type first and then the value

asserInternalType(boolean, return)
assertEquals(expected, return)

The first ensure the type is a documented return type and also force expected to be the same type
The second one is the classic discrete comparison of values

This format has 2 goodnes:

  • Keep clen the data provider from phpunit internals (method names)
  • Keep a consistent test format with a more clear error messages

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, it can be simplified even further: assertSame($expected, $return), which is the approach I'm about to push.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem with assersame is anyone can put a string in the provider.

Split in two make more clear 1:1 relations with method signature and avoid put false positive values in provider.

This is motivated in cases where the provider is implemented in child classes while the test method is not

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The contract for validators is to return boolean. Adding the assertion on
type is superfluous.

On Wed, Jul 22, 2015 at 8:01 AM, Maks3w notifications@github.com wrote:

In test/StaticValidatorTest.php
#26 (comment)
:

  •    $this->assertTrue(StaticValidator::execute(5, 'Between', [1, 10]));
    
  •    $this->assertTrue(StaticValidator::execute(5, 'Between', ['min' => 1, 'max' => 10]));
    
  •    return [
    
  •        'valid-positive-range'   => [5, 'Between', ['min' => 1, 'max' => 10], 'assertTrue'],
    
  •        'valid-negative-range'   => [-5, 'Between', ['min' => -10, 'max' => -1], 'assertTrue'],
    
  •        'invalid-positive-range' => [-5, 'Between', ['min' => 1, 'max' => 10], 'assertFalse'],
    
  •        'invalid-negative-range' => [5, 'Between', ['min' => -10, 'max' => -1], 'assertFalse'],
    
  •    ];
    
  • }
  • /**
  • \* @dataProvider parameterizedData
    
  • */
    
  • public function testExecuteValidWithParameters($value, $validator, $options, $assertion)
  • {
  •    $this->$assertion(StaticValidator::execute($value, $validator, $options));
    

The problem with assersame is anyone can put a string in the provider.

Split in two make more clear 1:1 relations with method signature and avoid
put false positive values in provider.

This is motivated in cases where the provider is implemented in child
classes while the test method is not


Reply to this email directly or view it on GitHub
https://github.com/zendframework/zend-validator/pull/26/files#r35209413.

Matthew Weier O'Phinney
matthew@weierophinney.net
https://mwop.net/

- Pass expected value from provider, and use `assertSame()`.
weierophinney added a commit that referenced this pull request Jul 22, 2015
weierophinney added a commit that referenced this pull request Jul 22, 2015
@weierophinney weierophinney self-assigned this Jul 22, 2015
@weierophinney weierophinney deleted the hotfix/16 branch July 23, 2015 13:34
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants