GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Add be_within 'fuzzy' matcher · Issue #77 · utPLSQL/utPLSQL

Add be_within 'fuzzy' matcher #77

New issue
Copy link
New issue
Copy link
Closed
#1076
Closed
Add be_within 'fuzzy' matcher#77
#1076
Copy link
Assignees
jgeballwasylow
Labels
enhancementidea

Description

@jgebal
jgebal
opened on Oct 17, 2016
Issue body actions

For numbers we should allow a comparison with a percent_off deviation.
The syntax:
ut.expect( a_actual =>1.23 ).to_( be_within( a_pct => 1, a_expected => 1.23456789 ) )
should give success
ut.expect( a_actual =>1.2 ).to_( be_within( a_pct => 1, a_expected => 1.23456789 ) )
should give success

Calculation logic.
a_actual between (a_expected - ((a_expected * a_pct)/100) ) and (a_expected + ((a_expected * a_pct)/100) )

Activity

Next
  1. jgebal
    added
    enhancement
    task
    on Oct 17, 2016
  2. jgebal
    added this to the This milestone has been deleted milestone on Oct 17, 2016
  3. jgebal
    self-assigned this
    on Oct 18, 2016
  4. jgebal
    added
    ready
    on Oct 18, 2016
  5. jgebal commented on Nov 21, 2016

    @jgebal
    jgebal
    on Nov 21, 2016
    MemberAuthor
    More actions

    Similar should be available for dates, timestamps and intevals (once suported)

  6. Pazus
    modified the milestones: This milestone has been deleted, This milestone has been deleted on Dec 7, 2016
  7. Pazus commented on Dec 7, 2016

    @Pazus
    Pazus
    on Dec 7, 2016
    Member
    More actions

    Rescheduled to version 3.1

  8. jgebal
    removed
    ready
    on Jan 18, 2017
  9. proldan commented on Mar 22, 2017

    @proldan
    proldan
    on Mar 22, 2017
    Contributor
    More actions

    What should pct mean in dates and intervals? Should it be a percentage of a day for dates?

  10. Shoelace commented on Mar 23, 2017

    @Shoelace
    Shoelace
    on Mar 23, 2017
    Member
    More actions

    that may not make a whole lot of sense..
    more useful for dates would be if it meant "number of seconds difference"
    ie so 1-jan-2017 10:12:13 would match 1-jan-2017 10:12:14

    i guess you could say 50% would mean +/- 12hours

  11. proldan
    added a commit that references this issue on Mar 30, 2017

    This commit solves issue utPLSQL#77

    d55b2ac
  12. jgebal commented on May 15, 2017

    @jgebal
    jgebal
    on May 15, 2017
    MemberAuthor
    More actions

    I think that for dates, timestamps and intervals we should not think of within in terms of PCT.
    For those data-types we should use interval as a measure of allowed deviation.
    so the syntax woule be like:

    ut.expect(sysdate).to_( be_within( interval '1' day, to_date( '20170515', 'yyyy-mm-dd' ) ) );
  13. jgebal
    removed this from the v3.1.0 milestone on Feb 5, 2018
  14. 20 remaining items

  15. PhilippSalvisberg commented on Jun 15, 2020

    @PhilippSalvisberg
    PhilippSalvisberg
    on Jun 15, 2020
    Member
    More actions

    The definition of the INTERVAL DAY TO SECOND Data Type is

    INTERVAL DAY TO SECOND stores a period of time in terms of days, hours, minutes, and seconds. This data type is useful for representing the precise difference between two datetime values.

    I like the Interval literals to express an interval in a human readable way. This helps especially for this use case. A comparison/assert with a tolerance. As @lwasylow I'd prefer a syntax as follows:

    ut.expect(l_actual_interval).to_be(l_expected_interval).with_tolerance(interval '5' minute);
    

    and for the second example

    ut.expect(l_actual_date).to_be(timestamp '2020-06-14 22:11.34').with_tolerance(interval '5' minute);
    

    It's a well know equal comparison with an optional tolerance.

    The tolerance can be an interval (year to month or day to second) or a number. Tolerance is applicable for datetime, timestamp, number comparisons. In case of datetime/timestamp a number tolerance is interpreted in days. This would be consistent with the datetime arithmetic of the Oracle Database.

  16. jgebal commented on Jun 16, 2020

    @jgebal
    jgebal
    on Jun 16, 2020
    MemberAuthor
    More actions

    I think there are two aspects here

    • should we allow for interval/interval/interval as acual/expexted/tolerance
    • what syntax shoul be used for this expectation?

    Seems like you're supportive of the firts but suggest to use alternative syntax to (...).to_be_within(...).of_(...)

  17. PhilippSalvisberg commented on Jun 16, 2020

    @PhilippSalvisberg
    PhilippSalvisberg
    on Jun 16, 2020
    Member
    More actions

    should we allow for interval/interval/interval as acual/expexted/tolerance

    Yes.

    what syntax shoul be used for this expectation?

    I favor (...).to_be(...).with_tolerance(...) over (...).to_be_within(...).of_(...). For me it is clearer which is the "tolerance" and which the value to compare to. However, there might be other things to consider like the return type of a method (making a fluent API harder or easier) and the consistency to other methods. I have not looked at these aspects.

  18. lwasylow commented on Jun 16, 2020

    @lwasylow
    lwasylow
    on Jun 16, 2020
    Member
    More actions

    For me a tolerance feel a better being second as for first part of name this can probably be modified there are multiple options like:
    nearly_equal or approx_equal instead of to_be

    I think with_tolerance also is a much clearer expresion and falls into a format as we passing expected first and then a modifier of that comparision whether is a join by or a distance.

  19. jgebal commented on Jun 16, 2020

    @jgebal
    jgebal
    on Jun 16, 2020
    MemberAuthor
    More actions

    One more:
    ut.expect(...).to_be_close_to(...).with_tolerance(...);

  20. PhilippSalvisberg commented on Jun 16, 2020

    @PhilippSalvisberg
    PhilippSalvisberg
    on Jun 16, 2020
    Member
    More actions

    Why change the first part and not keep the existing variant to_be? I see with_tolerance optional because the default is a tolerance of zero.

  21. lwasylow commented on Jun 16, 2020

    @lwasylow
    lwasylow
    on Jun 16, 2020
    Member
    More actions

    We need to change first part as currently we bene looking on to be within(3).of_(5) where 3 was a distance and 5 was a point from distance was measured.

  22. PhilippSalvisberg commented on Jun 17, 2020

    @PhilippSalvisberg
    PhilippSalvisberg
    on Jun 17, 2020
    Member
    More actions

    @lwasylow you were suggesting nearly_equal or approx_equal and @jgebal to_be_close_to instead of to_be. So, my question was why? Just because you like it more or is there some limitation regarding overloading of to_be?

  23. lwasylow commented on Jun 17, 2020

    @lwasylow
    lwasylow
    on Jun 17, 2020
    Member
    More actions

    @PhilippSalvisberg, apologies I misread your post. For some reason I assumed you reffered to to_be_within. There is no restriction in to_be. As for syntax I personally think to_be is not descriptive and can be be easily misunderstood with equal. Personally I would prefer something more descriptive as well as distance being mandatory value positive, with zero is just a worse version of equal.
    Hope that makes sense and clears.

  24. PhilippSalvisberg commented on Jun 17, 2020

    @PhilippSalvisberg
    PhilippSalvisberg
    on Jun 17, 2020
    Member
    More actions

    @lwasylow no problem.

    As for syntax I personally think to_be is not descriptive and can be be easily misunderstood with equal

    Actually that's what I like. Standalone to_be really means "to be equal to ... with zero tolerance". You can express it explicitly like this

    ut.expect(l_actual).to_be(l_expected).with_tolerance(0);
    

    or like this

    ut.expect(l_actual).to_be(l_expected);
    

    And it feels right. And also with non-default values for tolerance like this:

    ut.expect(l_actual).to_be(l_expected).with_tolerance(0.5);
    

    I am therefore voting against the introduction of additional keywords. Because I think it unnecessarily bloats the syntax of utPLSQL.

    We don't have to agree . Do whatever you and @jgebal think is best.

  25. jgebal commented on Jun 21, 2020

    @jgebal
    jgebal
    on Jun 21, 2020
    MemberAuthor
    More actions

    @PhilippSalvisberg, @lwasylow

    Keep in mind that utPSLQL suppoers two flavors of syntax for expectations:

    • shortcut syntax: ut.expect(l_actual).to_**matcher(...)[.options(...)...]**;
    • passing matcher to expectation: ut.expect(l_actual).to_( matcher(...)[.options(...)...] );

    So for fuzzy matcher we would need to name it be / ut_be.
    That way we would end up with syntax like:
    ut.expect( 1 ).to_( be( 2 ).with_tolerance( 1 ) );
    ut.expect( 1 ).not_to( be( 2 ).with_tolerance( 1 ) );
    ut.expect( 1 ).to_be( 2 ).with_tolerance( 1 );
    ut.expect( 1 ).not_to_be( 2 ).with_tolerance( 1 );

    The be in OOP it s used to represent equal identity in sense of "the same object instance" not "the same value" or "identical object".

    I think that be is too strong for this matcher and actually in PL/SQL it is quite impossible for two variables to point to (represent) the same object instance as assignments in PLSQL are done by deep copy of a variable.

    We could have used be for equality but since we have decided to use to_equal I se no value in changing it now.

    Overloading to_equal to support tolerance would also cause trouble with support for non-scalar data-types.

    It will not be possible to apply with_tolerance to cursor, object type, nested table.

    So we would need to add safety net for invalid syntax like:
    ut.expect( l_actual_cursor ).to_be( l_expected_cursor ).with_tolerance( 1 );

    The be_within is described as part of RSpec, which was as a reference for Domain Specific Language specification in utPLSQL expectations:
    https://relishapp.com/rspec/rspec-expectations/v/3-9/docs/built-in-matchers/be-within-matcher

    Thanks for all the inputs.

    I'm in favor of the following:

    begin
      ut.expect(interval).to_be_within(interval).of_(interval);
    
      ut.expect(date).to_be_within(interval).of_(interval);
      ut.expect(timestamp).to_be_within(interval).of_(timestamp);
      ut.expect(timestamp_tz).to_be_within(interval).of_(timestamp_tz);
      ut.expect(timestamp_ltz).to_be_within(interval).of_(timestamp_ltz);
    
      ut.expect(number).to_be_within(number).of_(number);
      ut.expect(number).to_be_within_pct(number).of_(number);
    end;
    Reacted by Philipp Salvisberg, Lukasz Wasylow, Samuel Nitsche and David Pyke
  26. PhilippSalvisberg commented on Jun 21, 2020

    @PhilippSalvisberg
    PhilippSalvisberg
    on Jun 21, 2020
    Member
    More actions

    Thank you, @jgebal for the detailed answer. You got me with the link to RSpec (and because utPLSQL is based on that) and the explanation regarding the technical issues.

    So, I support your approach.

  27. pesse commented on Jun 22, 2020

    @pesse
    pesse
    on Jun 22, 2020
    Member
    More actions

    @jgebal 's comments - as always a treasure of knowledge! ❤

  28. lwasylow
    linked a pull request that will close this issueFeature/rework matcher #1076on Feb 3, 2022
  29. jgebal
    closed this as completedin #1076on Feb 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

  • @jgebal
    jgebal
  • @lwasylow
    lwasylow

Labels

enhancementidea

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    You are visitor 01402520 — GeezerVison does not store the pages you look up.
    Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.