Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(math.vector): add tests for GetAngleBetweenVectorsOnPlane function #12974

Conversation

Dok11
Copy link
Contributor

@Dok11 Dok11 commented Sep 10, 2022

I generated 1000 variants of usage the GetAngleBetweenVectorsOnPlane function base on these values:

const possibleValues = [
        // negative values
        Number.MIN_SAFE_INTEGER,
        Number.MIN_SAFE_INTEGER / 2,
        -Math.PI,
        -0.0000000001,

        0,

        // positive values
        0.0000000001,
        Math.PI,
        Number.MAX_SAFE_INTEGER / 2,
        Number.MAX_SAFE_INTEGER,
    ];

So I got time comutation statistics that added to jsdoc.

What do you think about unit tests like this? Or probably we should set just several examples without edge values (like max_safe_integer)?

@azure-pipelines
Copy link

Please make sure to label your PR with "bug", "new feature" or "breaking change" label(s).
To prevent this PR from going to the changelog marked it with the "skip changelog" label.

@azure-pipelines
Copy link

@RaananW
Copy link
Member

RaananW commented Sep 12, 2022

Thanks for that!

I wonder - how were these numbers generated? And why do we need 1000 tests and not a few fixed (and tested) ones, including edge cases?

@Dok11
Copy link
Contributor Author

Dok11 commented Sep 12, 2022

I wonder - how were these numbers generated? And why do we need 1000 tests and not a few fixed (and tested) ones, including edge cases?

Yes, I want to discourse! =)

As edge cases I take Number.MIN_INTEGER_VALUE and max. Also I take zero and value close to zero 0.00000001 (negative and positive).
Also I choose some normal value between zero and max value — Math.PI (negative and positive).
In fact, I also added half value of Number.MIN and MAX_INTEGER_VALUE as normal value, but currenly I think it was redundant because Math.PI do same work.
So at least we have possible values:

const possibleValues = [
  Number.MIN_SAFE_INTEGER,
  -Math.PI,
  -0.0000000001,
  0,
  0.0000000001,
  Math.PI,
  Number.MAX_SAFE_INTEGER,
]

The function take 3 input Vector3 (3 input by 3 value), so to calculate all possible test cases we should Math.pow(possibleValues.length, 3 * 3); it equal to 40 353 607. Of course it is a lot. So I generate by random take value and got 1000 test cases.

Is all of them required? It is hard question. But I got some interesting insight.
After create these tests I start to modify the function and what I found - if we remove v0.normalize() and v1.normalize() then just a several tests of 1000 will failed, other of them works fine.
It's mean for me, these test keep guarantee to the function works well in most common tasks.

@RaananW
Copy link
Member

RaananW commented Sep 12, 2022

I wonder - how were these numbers generated? And why do we need 1000 tests and not a few fixed (and tested) ones, including edge cases?

Yes, I want to discourse! =)

As edge cases I take Number.MIN_INTEGER_VALUE and max. Also I take zero and value close to zero 0.00000001 (negative and positive). Also I choose some normal value between zero and max value — Math.PI (negative and positive). In fact, I also added half value of Number.MIN and MAX_INTEGER_VALUE as normal value, but currenly I think it was redundant because Math.PI do same work. So at least we have possible values:

const possibleValues = [
  Number.MIN_SAFE_INTEGER,
  -Math.PI,
  -0.0000000001,
  0,
  0.0000000001,
  Math.PI,
  Number.MAX_SAFE_INTEGER,
]

The function take 3 input Vector3 (3 input by 3 value), so to calculate all possible test cases we should Math.pow(possibleValues.length, 3 * 3); it equal to 40 353 607. Of course it is a lot. So I generate by random take value and got 1000 test cases.

Is all of them required? It is hard question. But I got some interesting insight. After create these tests I start to modify the function and what I found - if we remove v0.normalize() and v1.normalize() then just a several tests of 1000 will failed, other of them works fine. It's mean for me, these test keep guarantee to the function works well in most common tasks.

I will go over it in depth in an hour or two :-)

How were they generated? using the same function?

@Dok11
Copy link
Contributor Author

Dok11 commented Sep 12, 2022

How were they generated? using the same function?

No, just simple for loop. I dont save it but it was looking like:

for (let i = 0; i < 1000; i++) {
  testCases.push({
    v0: { x: getRandomPossibleValue(), /* y: ... */ },
    // same for
    // v1: 
    // normal
  });
}

after run it I fill the result and save it as fixed test cases as array in this PR.

@RaananW
Copy link
Member

RaananW commented Sep 12, 2022

How were they generated? using the same function?

No, just simple for loop. I dont save it but it was looking like:

for (let i = 0; i < 1000; i++) {
  testCases.push({
    v0: { x: getRandomPossibleValue(), /* y: ... */ },
    // same for
    // v1: 
    // normal
  });
}

after run it I fill the result and save it as fixed test cases as array in this PR.

I mean the results :-) You are testing the function against the results it has generated, right? So this test is only testing if the function has changed? Or have you generated the results using some other method?

@Dok11
Copy link
Contributor Author

Dok11 commented Sep 12, 2022

I mean the results :-) You are testing the function against the results it has generated, right? So this test is only testing if the function has changed? Or have you generated the results using some other method?

Right, I got current results by current state of the function with trust that it work correct.

So this test is only testing if the function has changed?

Yep.
If function work incorrect then tests wrong too.

What do you think, which is the best way to write unit tests in such case?

@RaananW
Copy link
Member

RaananW commented Sep 12, 2022

I mean the results :-) You are testing the function against the results it has generated, right? So this test is only testing if the function has changed? Or have you generated the results using some other method?

Right, I got current results by current state of the function with trust that it work correct.

So this test is only testing if the function has changed?

Yep. If function work incorrect then tests wrong too.

What do you think, which is the best way to write unit tests in such case?

Nope, I just wanted to be sure what is being tested :-)

@RaananW RaananW merged commit 05957b0 into BabylonJS:master Sep 12, 2022
@Dok11
Copy link
Contributor Author

Dok11 commented Sep 12, 2022

I just thought that this way to testing is good for long living high-order functions and I want to discourse it with you, what is the best way? Leave public functions without any tests is not good definitely, but how to test them right?

@Dok11
Copy link
Contributor Author

Dok11 commented Sep 12, 2022

And what do you think? Will some similar PRs be helpful if I make some of them? For me, it is an interesting way to get to know framework.

@RaananW
Copy link
Member

RaananW commented Sep 12, 2022

Of course. I would rather not have 1000 test cases (10-20 would be great :-)), but we are always happy for these kinds of PRs!

@Dok11
Copy link
Contributor Author

Dok11 commented Sep 13, 2022

I would rather not have 1000 test cases (10-20 would be great :-))

I understand you, but this situation looks like a potential problem when we talking about limited test cases:

After create these tests I start to modify the function and what I found - if we remove v0.normalize() and v1.normalize() then just a several tests of 1000 will failed, other of them works fine.

@Dok11 Dok11 deleted the test-babylon-math-vector-GetAngleBetweenVectorsOnPlane branch September 13, 2022 13:57
RaananW pushed a commit that referenced this pull request Dec 9, 2022
…on (#12974)

Former-commit-id: ba093fcbe5c697137fd55d4ef50f7eabc43cd255
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants