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

Introduce assertQueryLogTail() for better tests #9890

Closed
wants to merge 1 commit into from

Conversation

greg0ire
Copy link
Member

@greg0ire greg0ire commented Jul 9, 2022

Right now, you get an exception when trying to get a log line that is
out of bounds. It is hard to tell what the query log looks like when
that happens.

I decided to work on this after facing that issue on #9885

Right now, you get an exception when trying to get a log line that is
out of bounds. It is hard to tell what the query log looks like when
that happens.
@greg0ire greg0ire force-pushed the assert-query-log-tail branch from c2df07e to e5aba92 Compare July 9, 2022 16:07
@greg0ire greg0ire marked this pull request as ready for review July 9, 2022 16:48
'ALTER TABLE gh6823_user ADD CONSTRAINT FK_70DD1774FE54D947 FOREIGN KEY (group_id) REFERENCES gh6823_group (id)',
'ALTER TABLE gh6823_user ADD CONSTRAINT FK_70DD17746BF700BD FOREIGN KEY (status_id) REFERENCES gh6823_status (id)',
'ALTER TABLE gh6823_user_tags ADD CONSTRAINT FK_596B1281A76ED395 FOREIGN KEY (user_id) REFERENCES gh6823_user (id)'
);
Copy link
Member Author

Choose a reason for hiding this comment

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

This test does not exist on 2.12.x and is the main reason I want to do this. I'm not targeting 2.12.x in order to make the merge up less complicated.

'SELECT t0.id AS id_1, t0.driver_id AS driver_id_2, t3.id AS id_4, t3.name AS name_5, t0.owner_id AS owner_id_6, t7.id AS id_8, t7.name AS name_9 FROM Train t0 LEFT JOIN TrainDriver t3 ON t0.driver_id = t3.id INNER JOIN TrainOwner t7 ON t0.owner_id = t7.id WHERE t0.id = ?',
$this->getLastLoggedQuery()['sql']
$this->assertQueryLogTail(
'SELECT t0.id AS id_1, t0.driver_id AS driver_id_2, t3.id AS id_4, t3.name AS name_5, t0.owner_id AS owner_id_6, t7.id AS id_8, t7.name AS name_9 FROM Train t0 LEFT JOIN TrainDriver t3 ON t0.driver_id = t3.id INNER JOIN TrainOwner t7 ON t0.owner_id = t7.id WHERE t0.id = ?'
Copy link
Member

Choose a reason for hiding this comment

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

Does the ORM own any of these queries? What is the point of making assertions against SQL in functional tests? Given the experience of implementing compatibility with DBAL 4, I'd say that these tests cause more harm than good.

Copy link
Member Author

Choose a reason for hiding this comment

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

I see how that test isn't great, and anyone taking a look at ORM 3.x will see how it can get worse. Maybe making it easier to write such tests isn't a great idea. 🤔

What would be the alternative? Using the schema manager to get the charset and collation, and perform assertions on that?

Copy link
Member

@morozov morozov Jul 10, 2022

Choose a reason for hiding this comment

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

Are you talking about this specific test (testEagerLoadWithNullableColumnsGeneratesLeftJoinOnBothSides())? I don't see anything related to the charset and collation here.

Whatever the test is, the SQL solves a problem that the API consumer expects to be solved according to the API contract (e.g. the characters in the certain charset are stored/fetched correctly and are sorted according to the collation). A functional test should cover the consumer-facing API contract.

Copy link
Member Author

@greg0ire greg0ire Jul 10, 2022

Choose a reason for hiding this comment

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

Sorry, I was referring to the testCharsetCollationWhenCreatingForeignRelations, the test that prompted me to start this PR. I failed to notice your comment was on another test, but I suppose it applies to all of them.

Copy link
Member Author

Choose a reason for hiding this comment

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

@morozov I've started taking a look at this. For this one, I'm asserting that you can find a train without driver and vice versa

For the one below though, I'm not sure what to do: you cannot even persist a waggon that does not have a train. Should I test that we get a Doctrine\DBAL\Exception\NotNullConstraintViolationException? Or should I remove the test? After all, if the train id is mandatory, then it shouldn't matter whether we have a LEFT JOIN or an INNER JOIN

Copy link
Member

Choose a reason for hiding this comment

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

Maybe this test should use some different model where the referenced object is optional?

Copy link
Member

@morozov morozov Jul 11, 2022

Choose a reason for hiding this comment

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

From the documentation:

Whenever you query for an entity that has persistent associations and these associations are mapped as EAGER, they will automatically be loaded together with the entity being queried and is thus immediately available to your application.

I believe it implies that such entities need to be always loaded via a left join since otherwise, they won't load if the associated object is missing. But the test is named testEagerLoadWithNonNullableColumnsGeneratesInnerJoinOnOwningSide(). Why does the ORM need to generate an inner join? This is semantically incorrect.

Copy link
Member Author

Choose a reason for hiding this comment

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

Maybe this test should use some different model where the referenced object is optional?

I believe that's what the first test (testEagerLoadWithNullableColumnsGeneratesLeftJoinOnBothSides) is about.

Why does the ORM need to generate an inner join? This is semantically incorrect.

Since the referencing column is non nullable, there is a guarantee that the object exists so it shouldn't matter whether this is a LEFT JOIN or an INNER JOIN IMO.

Copy link
Member

Choose a reason for hiding this comment

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

It still doesn’t answer the question why, and it’s not entirely correct. Without an FK, there’s no guarantee that there always will be a match in the referenced table.

@morozov morozov mentioned this pull request Jul 10, 2022
@greg0ire
Copy link
Member Author

Closing in favor of #9895

@greg0ire greg0ire closed this Jul 11, 2022
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