Add tests to kill escaped mutants (#529)#545
Add tests to kill escaped mutants (#529)#545dbuhonov wants to merge 55 commits intoyiisoft:masterfrom
Conversation
dbuhonov
commented
Mar 13, 2026
| Q | A |
|---|---|
| Is bugfix? | ❌ |
| New feature? | ❌ |
| Breaks BC? | ❌ |
| Fixed issues | part of #529 |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #545 +/- ##
=============================================
- Coverage 100.00% 99.93% -0.07%
Complexity 655 655
=============================================
Files 43 43
Lines 1629 1605 -24
=============================================
- Hits 1629 1604 -25
- Misses 0 1 +1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
ec926d0 to
27f1743
Compare
… in EventsTraitTest.
…multiple test files.
…nd `RelationPopulator`
… behavior in RelationPopulator
There was a problem hiding this comment.
Pull request overview
This PR aims to increase mutation testing score (Issue #529) by adding/adjusting unit tests around ActiveRecord/ActiveQuery edge-cases (relations population/reset, upsert behavior, event dispatching, array access, etc.) and updating Infection configuration.
Changes:
- Added new tests covering previously untested branches/edge-cases in ActiveRecord, ActiveQuery, EventsTrait, Arrayable/ArrayAccess traits, RepositoryTrait, and MagicActiveRecord behavior.
- Introduced additional test stubs to exercise deep
via()relations, event-enabled models, and ArrayAccess edge-cases involving name collisions between properties and relations. - Updated
infection.json.distto ignore several specific mutators/locations.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Stubs/MagicActiveRecord/CategoryWithNameRelationArrayAccess.php | New stub to test ArrayAccess behavior when a relation name collides with a column/property name. |
| tests/Stubs/ActiveRecord/OrderItemWithDeepViaProfile.php | New stub to test deep via() chains and relation population behavior. |
| tests/Stubs/ActiveRecord/CustomerEventsModel.php | New stub enabling EventsTrait on a Customer derivative for event dispatch tests. |
| tests/Stubs/ActiveRecord/OrderItemWithConstructor.php | Doc comment fix to match the class name. |
| tests/RepositoryTraitTest.php | Adds coverage for find() behavior when condition is null (params should be ignored). |
| tests/MagicActiveRecordTest.php | Adds coverage for new-record save paths and property capability checks. |
| tests/EventsTraitTest.php | Adds coverage for delete prevention and “after” event dispatching + handler behavior. |
| tests/Driver/Pgsql/ActiveQueryTest.php | Adds PG-specific assertions for ModelRelationFilter condition types (array/json/scalar). |
| tests/ArrayableTraitTest.php | Adds coverage for extraFields() behavior when relations are populated. |
| tests/ArrayAccessTraitTest.php | Expands coverage for ArrayAccess edge-cases (property vs relation, magic properties, dependent-relation reset). |
| tests/ActiveRecordTest.php | Adds multiple tests for relation reset, populateProperties behavior, cloning semantics, linking/unlinking edge-cases, counters, overrides, and upsert defaults. |
| tests/ActiveQueryTest.php | Adds broad coverage around helper internals, joinWith parsing/behavior, relation population, via behavior, cloning, and filter application. |
| infection.json.dist | Adds multiple mutator ignore rules / regex-based ignores. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
tests/ActiveRecordTest.php
Outdated
| $this->assertStringContainsString('orders', serialize($customer)); | ||
|
|
||
| $customer->resetRelation('orders'); | ||
|
|
||
| $this->assertStringNotContainsString('orders', serialize($customer)); |
| "ConcatOperandRemoval": { | ||
| "ignore": [ | ||
| "Yiisoft\\ActiveRecord\\Trait\\MagicRelationsTrait::relationQuery", | ||
| "Yiisoft\\ActiveRecord\\Trait\\MagicRelationsTrait::relationNames" | ||
| ] | ||
| }, | ||
| "FalseValue": { | ||
| "ignore": [ | ||
| "Yiisoft\\ActiveRecord\\Event\\Handler\\SetValueOnUpdate::beforeUpsert" | ||
| ] | ||
| }, | ||
| "LogicalAnd": { | ||
| "ignore": [ | ||
| "Yiisoft\\ActiveRecord\\Internal\\JoinsWithBuilder::joinWithRelations" | ||
| ] | ||
| }, | ||
| "MatchArmRemoval": { | ||
| "ignore": [ | ||
| "Yiisoft\\ActiveRecord\\Event\\Handler\\SetValueOnUpdate::beforeUpsert" | ||
| ] | ||
| }, | ||
| "MethodCallRemoval": { | ||
| "ignore": [ | ||
| "Yiisoft\\ActiveRecord\\Internal\\JoinsWithBuilder::build" | ||
| ] | ||
| }, | ||
| "TrueValue": { | ||
| "ignore": [ | ||
| "Yiisoft\\ActiveRecord\\ActiveRecord::upsertInternal" | ||
| ], | ||
| "ignoreSourceCodeByRegex": [ | ||
| "protected function upsertInternal\\(\\?array \\$insertProperties = null, array\\|bool \\$updateProperties = true\\): void" | ||
| ] | ||
| }, | ||
| "UnwrapArrayValues": { | ||
| "ignore": [ | ||
| "Yiisoft\\ActiveRecord\\Internal\\JoinsWithBuilder::build" | ||
| ] | ||
| } |
There was a problem hiding this comment.
These exclusions are for survivors that are not obvious from the test diff itself, so I moved them into infection.json.dist intentionally to make them explicit and visible rather than leaving them hidden in the report only.
…ActiveRecordTest`.
There was a problem hiding this comment.
Pull request overview
This PR adds/extends PHPUnit coverage across ActiveRecord, ActiveQuery, events, array access/arrayable behavior, and several internal helpers to improve mutation score (Issue #529) by exercising previously untested branches and edge-cases.
Changes:
- Added many new tests around relation population/reset, upsert/link/unlink edge cases, event dispatching, and query/join/via behaviors.
- Introduced multiple new test stub ActiveRecord/ActiveQuery classes to support targeted scenarios (deep via relations, composite PKs, overridden internals, etc.).
- Updated Infection configuration with explicit mutator ignores for specific survivors.
Reviewed changes
Copilot reviewed 27 out of 27 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Stubs/MagicActiveRecord/CategoryWithNameRelationArrayAccess.php | New stub for ArrayAccess + magic relation name collision scenarios. |
| tests/Stubs/ActiveRecord/OrderWithCustomerProfileViaCustomerRelation.php | New stub to exercise nested “via” relation dependency handling. |
| tests/Stubs/ActiveRecord/OrderItemWithDeepViaProfile.php | New stub to cover deep via chain relation population. |
| tests/Stubs/ActiveRecord/OrderItemWithConstructor.php | Docblock fix for stub class name. |
| tests/Stubs/ActiveRecord/EmployeeWithPrototypeDossierRelation.php | New stub for prototype-cloned relation target and stricter PK checks. |
| tests/Stubs/ActiveRecord/CustomerWithUpdateInternalOverride.php | New stub to test overridable updateInternal(). |
| tests/Stubs/ActiveRecord/CustomerWithRefreshInternalOverride.php | New stub to test overridable refreshInternal(). |
| tests/Stubs/ActiveRecord/CustomerWithOverriddenRelationQuery.php | New stub to test overridable relation query creation. |
| tests/Stubs/ActiveRecord/CustomerWithDeleteInternalOverride.php | New stub to test overridable deleteInternal(). |
| tests/Stubs/ActiveRecord/CustomerSetValueOnUpdateUpsert.php | New stub for SetValueOnUpdate behavior during upsert. |
| tests/Stubs/ActiveRecord/CustomerEventsModel.php | New stub enabling EventsTrait on Customer. |
| tests/Stubs/ActiveRecord/CompositePrimaryKeyDossier.php | New stub for composite PK relation/linking scenarios. |
| tests/Stubs/ActiveQuery/SingleModelArrayActiveQuery.php | New stub to ensure one() path doesn’t fall back to all(). |
| tests/Stubs/ActiveQuery/OverriddenPrimaryTableNameActiveQuery.php | New stub to cover overriding primary table resolution. |
| tests/Stubs/ActiveQuery/OverriddenCreateModelsActiveQuery.php | New stub to cover overriding model creation from rows. |
| tests/Stubs/ActiveQuery/MissingLinkValuesActiveQuery.php | New stub for missing link values during relation population. |
| tests/Stubs/ActiveQuery/CreateModelsExceptionOnEmptyRowsActiveQuery.php | New stub ensuring empty populate doesn’t call createModels(). |
| tests/Stubs/ActiveQuery/AlternativeActiveQuery.php | New stub for alternate ActiveQuery implementation. |
| tests/RepositoryTraitTest.php | Added coverage for find() behavior with null condition/params handling. |
| tests/MagicActiveRecordTest.php | Added tests for save/update behavior and property accessor edge-cases. |
| tests/EventsTraitTest.php | Expanded event dispatch/handler behavior coverage (after-events, soft delete, defaults, etc.). |
| tests/Driver/Pgsql/ActiveQueryTest.php | Added PG-specific assertions for ModelRelationFilter conditions. |
| tests/ArrayableTraitTest.php | Added extraFields() coverage. |
| tests/ArrayAccessTraitTest.php | Expanded ArrayAccess tests for properties vs relations and magic properties. |
| tests/ActiveRecordTest.php | Added extensive relation reset/dependency, PK error message, upsert/link/unlink/counters, override hooks tests. |
| tests/ActiveQueryTest.php | Added extensive coverage for populate/dedup, joinWith validation, viaTable callable, relation population internals. |
| infection.json.dist | Added explicit mutator ignore configuration for remaining survivors. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
tests/Stubs/ActiveRecord/CustomerWithRefreshInternalOverride.php
Outdated
Show resolved
Hide resolved
tests/Stubs/ActiveRecord/CustomerWithOverriddenRelationQuery.php
Outdated
Show resolved
Hide resolved
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
| public function testModelRelationFilterUsesArrayOverlapsForArrayColumns(): void | ||
| { | ||
| $query = Promotion::query()->link(['array_item_ids' => 'id']); | ||
|
|
||
| ModelRelationFilter::apply($query, [ | ||
| ['id' => 1], | ||
| ]); | ||
|
|
||
| $where = $query->getWhere(); | ||
|
|
||
| $this->assertInstanceOf(ArrayOverlaps::class, $where); | ||
| $this->assertSame('array_item_ids', $where->column); | ||
| $this->assertInstanceOf(ArrayValue::class, $where->values); | ||
| $this->assertSame([1], $where->values->value); | ||
| } |
There was a problem hiding this comment.
Doesn't it duplicate the next test?
There was a problem hiding this comment.
Merged these checks into a single test: testModelRelationFilterUsesArrayOverlapsWithArrayValueAndColumnSchemaForArrayColumns, since both were covering the same ColumnType::ARRAY
|
|
||
| namespace Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord; | ||
|
|
||
| final class CustomerWithDeleteInternalOverride extends Customer |
There was a problem hiding this comment.
It is used testDeleteInternalCanBeOverridden
| use Yiisoft\ActiveRecord\ActiveRecordInterface; | ||
| use Yiisoft\ActiveRecord\Tests\Stubs\ActiveQuery\AlternativeActiveQuery; | ||
|
|
||
| final class CustomerWithOverriddenRelationQuery extends Customer |
There was a problem hiding this comment.
It is used testCreateRelationQueryCanBeOverridden
|
|
||
| use Yiisoft\ActiveRecord\ActiveRecordInterface; | ||
|
|
||
| final class CustomerWithRefreshInternalOverride extends Customer |
There was a problem hiding this comment.
it is used testRefreshInternalCanBeOverridden
|
|
||
| namespace Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord; | ||
|
|
||
| final class CustomerWithUpdateInternalOverride extends Customer |
There was a problem hiding this comment.
It is used testUpdateInternalCanBeOverridden
| use Yiisoft\ActiveRecord\ActiveRecord; | ||
| use Yiisoft\ActiveRecord\ActiveRecordInterface; | ||
|
|
||
| final class EmployeeWithPrototypeDossierRelation extends ActiveRecord |
There was a problem hiding this comment.
It is used testLinkExistingRecordToNewWithStrictPrimaryKeyValidationUsesLinkValues
…arity and coverage.
CHANGELOG.md
Outdated
| ## 1.0.3 under development | ||
|
|
||
| - no changes in this release. | ||
| - Test #529: Increase MSI to 100% (@dbuhonov) |
There was a problem hiding this comment.
These changes don't touch package code. Line in changelog is not needed.
|
Up review pls |