As discovered in #3001398-18: format_size() fixes, SizeTest needs

  1. some love, rejuvenating it to proper PHPUnit concepts - first and foremost introducing @dataproviders for making tests more atomic.
  2. +++ b/core/tests/Drupal/KernelTests/Core/Common/SizeTest.php
    @@ -48,11 +53,8 @@ protected function setUp() {
    +        $this->assertSame($expected, $result, $expected . ' == ' . $result . ' (' . $input . ' bytes)');

    What is the reason for putting $expected == $result in here? PHPUnit provides this information out of the box.

  3. +++ b/core/tests/Drupal/KernelTests/Core/Common/SizeTest.php
    @@ -62,11 +64,8 @@ public function testCommonFormatSize() {
    -      $this->assertEqual(
    -        $size,
    -        ($parsed_size = Bytes::toInt($string = format_size($size, NULL))),
    -        $size . ' == ' . $parsed_size . ' (' . $string . ')'
    -      );
    +      $parsed_size = Bytes::toInt($string = format_size($size, NULL));
    +      $this->assertEquals($size, $parsed_size, $size . ' == ' . $parsed_size . ' (' . $string . ')');

    To be honest I think we should improve the readability of this test and assign $string outside.

Comments

mondrake created an issue. See original summary.

longwave’s picture

Status: Active » Needs review
StatusFileSize
new3.45 KB

Unified the two tests into a single test with a data provider and (hopefully) modernised it to current standards.

mondrake’s picture

Status: Needs review » Reviewed & tested by the community

Looks good. Either this or #3001398: format_size() fixes will require a reroll, but let's see what lands first.

mondrake’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/tests/Drupal/KernelTests/Core/Common/SizeTest.php
@@ -12,62 +12,46 @@
+      [TRUE, '2 bytes', 2],

ooops no, this is in the rounded part, not the exact

EDIT: or not? it's in the rounded part in the current test, but since it's below 1KB in fact it shouldn't?

mondrake’s picture

Status: Needs work » Needs review
wengerk’s picture

Thanks for your tests ! I would go even beyond on modernisation & best practices to avoid any business logic or any if conditions.

I would probably end up writing separate tests for the following if case

For non-rounded values, cross-test that Bytes::toInt() returns the original input.

It would be by fare more elegant & easier to read if you provide 2 dataProviders & split the tests on 2 separated logics.

Here is my suggestion

  • testCommonFormatSize with a provider providerTestCommonFormatSize
  • testCommonFormatSizeCrossTestToInt with a provider providerTestCommonFormatSizeToInt

What do you think ?

wengerk’s picture

Status: Needs review » Needs work
wengerk’s picture

Status: Needs work » Needs review
StatusFileSize
new3.83 KB
new2.85 KB

Here are my suggestions, what do you think about it ?
By decoupling, we can add a proper @covers and we simplify the test readability.

PS: We could maybe rename the testCommonFormatSizeCrossTestToInt to something better.

Status: Needs review » Needs work

The last submitted patch, 8: 3001846-08.patch, failed testing. View results

wengerk’s picture

Status: Needs work » Needs review
StatusFileSize
new3.83 KB
new792 bytes

Oppsy I made a typo on my copy/past provider of tests ... sorry

longwave’s picture

+++ b/core/tests/Drupal/KernelTests/Core/Common/SizeTest.php
@@ -12,62 +12,66 @@
+  public function testCommonFormatSizeCrossTestToInt($expected, $size) {
+    $this->assertEquals($expected, Bytes::toInt($size));

This doesn't actually cross-test; it should call format_size($expected) and then check that Bytes::toInt() returns the original value.

wengerk’s picture

This is the idea @longwave to rename this. UnitTest should not do some cross-test it's not a best practice. Otherwise if the first format_size fails it will obviously fail the "cross-test" which is not very useful. We can assert it works by himself just by using the provider.

If we want to assert Bytes::toInt we can do it in this test but we have to rename it, indeed as I suggest it in #8.

What do you think ? Let's discuss about it !

wengerk’s picture

StatusFileSize
new3.79 KB
new852 bytes

Here are the changes according #8, #11 & #12.

longwave’s picture

There is already a standalone test for Bytes::toInt() in \Drupal\Tests\Component\Utility\BytesTest, so I don't think we need another unit test of that method here?

The point of the cross-test seems to be ensuring that Bytes::toInt() can correctly reverse whatever format_size() produces (for non-rounded values at least), not sure whether that is actually worthwhile though.

wengerk’s picture

Status: Needs review » Needs work

Your are perfectly right, I didn't see the existing tests before !
Then we should remove the tests I added, my bad.

I don't think we have to cross-test this, I mean all the necessary assertions are already done by the existing \Drupal\Tests\Component\Utility\BytesTest::testToInt.

Let's remove my unnecessary testBytesToInt & providerTestBytesToInt.

krzysztof domański’s picture

Status: Needs work » Needs review
StatusFileSize
new3.28 KB

Here are the changes according #2 and #13.

I remove testBytesToInt & providerTestBytesToInt. I added $exact as the default parameter.

Now it looks like this:

public function testCommonFormatSize($expected, $input, $exact = TRUE) {
  $size = format_size($input, NULL);
  $this->assertEquals($expected, $size);

  // For non-rounded values, cross-test that Bytes::toInt() returns the
  // original input.
  if ($exact) {
    $this->assertEquals($input, Bytes::toInt($size));
  }
}

public function providerTestCommonFormatSize() {
  $kb = Bytes::KILOBYTE;
  return [
    ['1 byte', 1],
    ['2 bytes', 2],
    ['1 KB', $kb],
    ['1 MB', pow($kb, 2)],
    ['1 GB', pow($kb, 3)],
    ['1 TB', pow($kb, 4)],
    ['1 PB', pow($kb, 5)],
    ['1 EB', pow($kb, 6)],
    ['1 ZB', pow($kb, 7)],
    ['1 YB', pow($kb, 8)],
    'Rounded to 1 MB - not 1000 or 1024 kilobyte' => ['1 MB', ($kb * $kb) - 1, FALSE],
    'Decimal Megabytes' => ['3.46 MB', 3623651, FALSE],
    'Decimal Petabytes' => ['59.72 PB', 67234178751368124, FALSE],
    'Decimal Yottabytes' => ['194.67 YB', 235346823821125814962843827, FALSE],
  ];
}

What do you think?

krzysztof domański’s picture

I think the following code is not readable.

'Rounded to 1 MB - not 1000 or 1024 kilobyte' => ['1 MB', ($kb * $kb) - 1, FALSE],
'Decimal Megabytes' => ['3.46 MB', 3623651, FALSE],
'Decimal Petabytes' => ['59.72 PB', 67234178751368124, FALSE],
'Decimal Yottabytes' => ['194.67 YB', 235346823821125814962843827, FALSE],

Better earlier version?

//'Rounded to 1 MB - not 1000 or 1024 kilobyte'
['1 MB', ($kb * $kb) - 1, FALSE],
//'Decimal Megabytes'
['3.46 MB', 3623651, FALSE],
//'Decimal Petabytes'
['59.72 PB', 67234178751368124, FALSE],
//'Decimal Yottabytes'
['194.67 YB', 235346823821125814962843827, FALSE],
wengerk’s picture

Status: Needs review » Needs work

Thanks for reroll & work on it.

For #16 the idea was to not do cross-test. So only remove the testBytesToInt & providerTestBytesToInt of #13 we don't want to mix 2 kind of assertion on the same test (plus BytesToInt is already covered).

About #17 I agree let's change it (again).

Don't forget to upload an interdiff on changes, would be easier to review :)

krzysztof domański’s picture

Status: Needs work » Needs review
StatusFileSize
new3.13 KB
new1.66 KB
new1.7 KB

@Kevin Thanks for the previous tips!

I removed testBytesToInt & providerTestBytesToInt #15.
I corrected #17.

There is already a standalone test for Bytes::toInt() in \Drupal\Tests\Component\Utility\BytesTest, so I don't think we need another unit test of that method here?

The point of the cross-test seems to be ensuring that Bytes::toInt() can correctly reverse whatever format_size() produces (for non-rounded values at least), not sure whether that is actually worthwhile though.

The cross-test (with Bytes::toInt()) could look like following code, but it is not necessary. Let's not add this. Do you agree with me?

public function testCommonFormatSizeConversionTest($input) {
  $size = format_size($input, NULL);
  $this->assertEquals($input, Bytes::toInt($size));
}

public function providerTestCommonFormatSizeConversionTest() {
  $kb = Bytes::KILOBYTE;
  return [
    1,
    2,
    $kb,
    pow($kb, 2),
    pow($kb, 3),
    pow($kb, 4),
    pow($kb, 5),
    pow($kb, 6),
    pow($kb, 7),
    pow($kb, 8),
  ];
}
wengerk’s picture

I agree with you as that's exactly what I try to explain (maybe badly ^^).

We don't need the test testCommonFormatSizeConversionTest for the following reasons:

The Bytes::toInt is already covered by \Drupal\Tests\Component\Utility\BytesTest::testToInt . And the result of format_size are covered by our new test testCommonFormatSize.

So both Bytes::toInt & format_size output/input are covered. if our tests on format_size fail then the output will be different as expected (aka not compliant with Bytes::toInt). We don't need to add a cross-test anywhere.

I can no longer RTBC this. Anyone else want to review / test / RTBC?

longwave’s picture

Status: Needs review » Reviewed & tested by the community

#19 looks great to me.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Much more readable and explicit - nice work - and once format_size becomes a class this can be easily converted to a unit test.

Committed and pushed f321b4aa69 to 8.7.x and 228c146440 to 8.6.x. Thanks!

  • alexpott committed f321b4a on 8.7.x
    Issue #3001846 by wengerk, Krzysztof Domański, longwave, mondrake:...

  • alexpott committed 228c146 on 8.6.x
    Issue #3001846 by wengerk, Krzysztof Domański, longwave, mondrake:...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.