Follow-up to #2827100: Improve test coverage and function docs

Issue #2827100: Improve test coverage and function docs made some changes to the math_expression.test file, but in doing that it was noticed that the tests there are not well documented and have some gaps.

In particular:
- Add function documentation for clarity and to assist phpcs
- Switch from deprecated rand() function to mt_rand()
- Test equality in assertFloat more accurately: the existing test only checked absolute value, but we need to check sign and, just in case, for NaN and Inf as well.
- Run the Arithmetic tests through a loop as suggested in a previous comment, rather than just once.
- Include an appropriate assertion message for each test, rather than the default, making it easier to see what operations passed/failed.
- Remove commented-out tests for min() and max(): Those functions cannot work and should be removed from the codebase (there is no provision for internal functions having anything other than a single value).
- Add in tests for overwriting a variable value, operating on two different variables in one expression.
- Add tests for the internal predefined constants 'pi' and 'e'.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

rivimey created an issue. See original summary.

rivimey’s picture

FileSize
14.5 KB

My first attempt at fixing those.

I have included some source changes: split lines for additional clarity, and changed the variable name $math_expression to $math_expr, to aid comprehension.

rivimey’s picture

Assigned: rivimey » Unassigned
Status: Active » Needs review

Status: Needs review » Needs work

The last submitted patch, 2: ctools-n2830393-1.patch, failed testing.

rivimey’s picture

patch failed to apply because it is based on top of another as yet unapplied patch in another issue.
Can I tell testbot to apply the other patch first?

DamienMcKenna’s picture

Status: Needs work » Postponed

Lets get #2827100: Improve test coverage and function docs fixed and applied first, then work on other improvements.

rivimey’s picture

Patch ctools-n2830393-1-eval.patch applies against current 7.x-1.x ctools (ie does not require #2827100: Improve test coverage and function docs) but it does assume #1958538: Improve math expression engine ctools-n1958538-55.patch has been applied.

I have only integrated the two developments, but have not further extended the tests to include the (significant) additional functionality found in [1958538].

In 2827100 are a few changes to tests/math_expression.test which mean this patch will no longer apply. I have therefore included ctools-n2830393-1-after-2827100-52.txt for that situation.

DamienMcKenna’s picture

Status: Postponed » Needs work

Lets reroll this, now that #2827100: Improve test coverage and function docs has been committed.

rivimey’s picture

I am now assuming that #1958538: Improve math expression engine will be merged

This reroll of the patch has two files:
- a version that includes both 1958538-64 and my changes for this issue
- a version that includes this issue's changes, to be applied after 1958538 is merged.

rivimey’s picture

Status: Needs work » Needs review
rivimey’s picture

darrenwh’s picture

Status: Needs review » Needs work

All looks good, but.

+++ b/includes/math-expr.inc
@@ -1,388 +1,955 @@
+  private function nfx($expr) {

This is a very very long method? Perhaps break it out into smaller sub methods? (Perhaps it can be addressed at later date, including the pfx method)

Some more things

  1. +++ b/tests/math_expression.test
    @@ -20,142 +20,302 @@ class CtoolsMathExpressionTestCase extends DrupalWebTestCase {
    +      // Equal if both an infinity .
    

    There is a space before the period

  2. +++ b/tests/math_expression.test
    @@ -20,142 +20,302 @@ class CtoolsMathExpressionTestCase extends DrupalWebTestCase {
    -    $math_expression = new ctools_math_expr();
    ...
    +    $this->assertFloat(3.1415926535898, $math_expr->evaluate('pi'));
    

    Looking at the ctools_math_expr class pi and e are declared using the php function pi() and exp(1) why are they not tested against these values? Is there something I'm missing here?

rivimey’s picture

Darren, re the pi() values etc; the reason was that at one time the values being assigned were being truncated to e.g. 3.1415 and so a pi() value would not have matched. I guess that reason is now gone. The only other downside I can think of would be if the php pi() function was not returning the correct value either, which I guess would be a more serious issue :-) ... I'll change it.

Re nfx() -- well, this code was originally refactored by others several years ago and while I agree it is quite poorly structured, I have been reluctant to make structural changes. I'll have a look and see whether there are any low-hanging fruit.

rivimey’s picture

Darren, I have had a look at refactoring nfx() and cannot see any simple refactors that make sense to me to do at this point.

There are some things - for example I can relatively easily extract the close paren code (lines 475..516) into nfx_closeparan() and if other branches of the if..else were as easy that would have been good, but that part is unusual and extracting other branches merely obscures the overall logic further. I cannot see worthwhile common code to extract either; there are a couple of things, but nothing of note.

To do it well would, IMO, require creating a new structure, possibly a new class, with all the work and re-testing that would require, and I do not think the result would be worth the effort.

If you can see things I've not mentioned, I am still up for small changes.

One of the changes I am wondering about is to make nfx() return NULL rather than FALSE when an error is detected; this would mean the function was not returning two different types of value and thus satisfy phpstorm's code analyser (which doesn't track the type of multi-type variables well). However, the code is itself ok, and so such a change would essentially be cosmetic.

rivimey’s picture

Ok, some updates for the pi, exp issues and the comment.

The patch included here from 1958538 in the 'incl' version is from comment 72

rivimey’s picture

Status: Needs work » Needs review
DamienMcKenna’s picture

This didn't get into 1.13, maybe it will get into 1.14.

We need to try getting this to RTBC.

The last submitted patch, 15: ctools-n2830393-incl1958538-15.patch, failed testing. View results

TR’s picture

FileSize
64.19 KB

I tried re-testing the patch from #15 to see what phpcs would report (I noticed there are a lot of coding standards issues in the patch), but I see the patch no longer applies.

Here's a re-roll of the patch ctools-n2830393-incl1958538-15.patch from #15 - let's see what the testbot reports then I will re-roll it again with coding standards fixes. It's not clear to me how useful this is, because it mixes up changes from this issue and from #1958538: Improve math expression engine, but it's a start.

One question though:
I see this patch adds the constant 'c' (speed of light), although that is not discussed above.
All the other defined constants are dimensionless - pure numbers like pi and e. 'c' would be the only constant with dimensions, which naturally brings with it the question of what units are used for this constant and how are the units stored/communicated to users and how conversion of units is handled in math expressions. Because of this, I feel adding 'c' should be removed from this patch, as it is a feature request which requires some decision on how to carry around and use dimensioned constants.

TR’s picture

And here's the same patch as #19, with most of the coding standards fixed. See the interdiff for changes. (Entirely doc comments, comments, and type hints). I did NOT change class names or class properties to upperCamel, as I feel that would be out of scope for this issue, so there are going to be some remaining coding standards warnings.

Status: Needs review » Needs work

The last submitted patch, 20: 2830393-20.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

TR’s picture

Status: Needs work » Needs review
darrenwh’s picture

Status: Needs review » Needs work
  1. +++ b/ctools.api.php
    @@ -152,30 +154,55 @@ function hook_ctools_api_hook_alter(&$list) {
    + * One usecase would be to create your own function in your module and
    

    should say use case

  2. +++ b/includes/math-expr.inc
    @@ -1,391 +1,960 @@
    + * @file
    

    Classes don't need @file notation

  3. +++ b/includes/math-expr.inc
    @@ -1,391 +1,960 @@
    +      $fnn = $matches[1];
    

    Could this function be named more clearly than $fnn?

  4. +++ b/includes/math-expr.inc
    @@ -1,391 +1,960 @@
    +    foreach ($this->userfuncs as $fnn => $dat) {
    

    Variable name could do with being more descriptive.

  5. +++ b/includes/math-expr.inc
    @@ -1,391 +1,960 @@
    +          $fnn = $matches[1];
    

    Variable naming again

  6. +++ b/includes/math-expr.inc
    @@ -1,391 +1,960 @@
    +            $fdef = $this->funcs[$fnn];
    

    Variable naming.

  7. +++ b/includes/math-expr.inc
    @@ -1,391 +1,960 @@
    +          // yay... recursion!!!!
    

    Needs a capital letter at start.

I believe a coding standards cleanup has been done on all the source so this should cover some of the simple things like capital letters, but there are many abbreviated variables that would be better of being more descriptive as not all developers will recognise them particularly non native English speakers.

TR’s picture

Status: Needs work » Needs review
FileSize
69.94 KB

@darrenwh:

1) Fixed.

2) From the Drupal coding standards:

The @file doc block MUST be present for all PHP files, with one exception: files that contain a namespaced class/interface/trait, whose file name is the class name with a .php extension, and whose file path is closely related to the namespace (under PSR-4 or a similar standard), SHOULD NOT have a @file documentation block.

In this case, class ctools_math_expr is in a file called math-expr.inc. There is no .php extension, the class name is not the same as the file name, and the class is not namespaced, so it absolutely SHOULD have a @file comment according to the coding standards. That's why the PHPCS coding standards check does not complain about @file here.

3)

Could this function be named more clearly than $fnn?

Yes, but it's currently used 20 times in math-expr.inc. This issue didn't name that function, and it didn't change how that function is used. I think the name should be changed, but I think that's outside the scope of this issue.

4), 5), 6) Same as 3).

7) Fixed.

I would appreciate a comment about the 'c' variable usage that I asked about above, and a review of the substance of the issue. This patch already fixes more than 700 coding standards issues, and it only introduced ONE new coding standards issues (usecase -> use case, fixed in this new patch), so I suggest that further coding standards problems be a part of a separate issue so that we can move this along.

Status: Needs review » Needs work

The last submitted patch, 24: 2830393-24.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

TR’s picture

Status: Needs work » Needs review

CTools PHP 5.3 tests are still failing because of #2783113: Using trait without PHP 5.4 requirement breaks Drupal CI of all modules that require UUID, but PHP 5.4+ tests work. Test failure was not because of this patch.

DamienMcKenna’s picture

darrenwh’s picture

Status: Needs review » Needs work
  1. +++ b/includes/math-expr.inc
    @@ -1,391 +1,960 @@
    +  protected $userfuncs;
    

    This should be in lower camel case

  2. +++ b/includes/math-expr.inc
    @@ -1,391 +1,960 @@
    +  protected $constvars;
    

    This should be in lower camel case

  3. +++ b/includes/math-expr.inc
    @@ -1,391 +1,960 @@
    +  protected $simplefuncs;
    

    This should be in lower camel case

  4. +++ b/includes/math-expr.inc
    @@ -1,391 +1,960 @@
    +  protected $binaryops;
    

    This should be in lower camel case

  5. +++ b/includes/math-expr.inc
    @@ -1,391 +1,960 @@
    +  private function nfx($expr) {
    

    Wonder if this would be better off in its own class?

TR’s picture

Status: Needs work » Needs review

As I said in #24,

I would appreciate a comment about the 'c' variable usage that I asked about above, and a review of the substance of the issue. This patch already fixes more than 700 coding standards issues, and it only introduced ONE new coding standards issues (usecase -> use case, fixed in this new patch), so I suggest that further coding standards problems be a part of a separate issue so that we can move this along.

So, back to "Needs review"

If you want to "fix" CTools by making all the class variables camel case like phpcs wants, then please open a new issue where you can fix all 148 of those at once. That's way off topic for this issue.

darrenwh’s picture

Status: Needs review » Reviewed & tested by the community
joelpittet’s picture

Status: Reviewed & tested by the community » Needs review
Issue tags: -Needs tests
FileSize
16.36 KB

I'm putting up a tests only patch to smoke test this.

@TR I don't have enough domain knowledge to answer your question about "dimensioned constants" but if it doesn't make sense I'd agree to your assessment to remove the example.

Status: Needs review » Needs work

The last submitted patch, 31: 2830393-31-tests-only.patch, failed testing. View results

TR’s picture

Test failure in #31 was because yesterday there was a Drupal core commit that introduce short array syntax into core - this makes ALL PHP 5.3 tests fails. See #2482549: Ignore node_module folder in core to use Drupal with npm/grunt/nodejs

joelpittet’s picture

Thanks @TR for the heads up. I’ll wait till that commit is fixed.

joelpittet’s picture

rivimey’s picture

Status: Needs work » Reviewed & tested by the community

I believe that this patch is operating correctly: The purpose of the patch is to improve test coverage, and it has found some issues...
[ https://www.drupal.org/pift-ci-job/1366113 ] : pow(), if() and min()/max() all fail. That is, the code being tested is failing.

The reason for failure is that these functions **never have worked**. The math-expr code doesn't understand two-arg named functions and never has done so, despite appearances to the contrary. It's a while ago since I did the original patch, but I recall something about another patch that added n-arg functions properly, but it has never been included here.

In my opinion, the correct action at this point is to accept this patch and then create a new issue to fix the main code -- I expect at this point the right fix is to remove all two-operand functions, but after all the messing around with what should have been a simple commit, I am no longer willing to help with that.

MustangGB’s picture

Status: Reviewed & tested by the community » Closed (duplicate)

Maintainers don't appear to want to commit updated tests with broken code, or updated code without tests, and as there is a lot of overlap/cross-blocking I've taken the latest and greatest from here and merged it with #1958538: Improve math expression engine in an attempt to pull them both together and prevent future conflicts, so closing this as a duplicate.

rivimey’s picture

Hey MustangGB, thanks for grasping the bull with this one. Great this might someday get merged in!