Skip to content

Commit

Permalink
Merge pull request #603 from tienvx/increase-more-code-coverage
Browse files Browse the repository at this point in the history
Test Step value object
  • Loading branch information
tienvx committed Apr 10, 2022
2 parents 35cba33 + a1487f8 commit 31bdf06
Show file tree
Hide file tree
Showing 29 changed files with 566 additions and 159 deletions.
13 changes: 12 additions & 1 deletion src/Entity/Model/Revision.php
Expand Up @@ -33,6 +33,7 @@ class Revision extends BaseRevision
* @Assert\Type("\Tienvx\Bundle\MbtBundle\ValueObject\Model\Place")
* })
* @Assert\Valid
* @Assert\Count(min=1)
*/
protected array $places = [];

Expand All @@ -42,6 +43,7 @@ class Revision extends BaseRevision
* @Assert\Type("\Tienvx\Bundle\MbtBundle\ValueObject\Model\Transition")
* })
* @Assert\Valid
* @Assert\Count(min=1)
*/
protected array $transitions = [];

Expand All @@ -53,12 +55,17 @@ public function validatePlacesInTransitions(ExecutionContextInterface $context,
foreach ($this->transitions as $index => $transition) {
if ($transition instanceof TransitionInterface) {
$fromPlaces = $transition->getFromPlaces();
$toPlaces = $transition->getToPlaces();
if (!$fromPlaces && !$toPlaces) {
$context->buildViolation('mbt.model.missing_places')
->atPath(sprintf('transitions[%d]', $index))
->addViolation();
}
if ($fromPlaces && array_diff($fromPlaces, array_keys($this->places))) {
$context->buildViolation('mbt.model.places_invalid')
->atPath(sprintf('transitions[%d].fromPlaces', $index))
->addViolation();
}
$toPlaces = $transition->getToPlaces();
if ($toPlaces && array_diff($toPlaces, array_keys($this->places))) {
$context->buildViolation('mbt.model.places_invalid')
->atPath(sprintf('transitions[%d].toPlaces', $index))
Expand All @@ -73,6 +80,10 @@ public function validatePlacesInTransitions(ExecutionContextInterface $context,
*/
public function validateStartTransitions(ExecutionContextInterface $context, $payload): void
{
if (0 === count($this->transitions)) {
return;
}

$startTransitions = array_filter(
$this->transitions,
fn ($transition) => $transition instanceof TransitionInterface && 0 === count($transition->getFromPlaces())
Expand Down
6 changes: 0 additions & 6 deletions src/Entity/Task.php
Expand Up @@ -4,7 +4,6 @@

use DateTime;
use DateTimeInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\Embedded;
Expand Down Expand Up @@ -78,11 +77,6 @@ class Task extends TaskModel
*/
protected DateTimeInterface $updatedAt;

public function __construct()
{
$this->bugs = new ArrayCollection();
}

/**
* @ORM\PrePersist
*/
Expand Down
5 changes: 1 addition & 4 deletions src/Generator/RandomGenerator.php
Expand Up @@ -49,6 +49,7 @@ public function generate(TaskInterface $task): iterable
$places = $this->modelHelper->getStartPlaceIds($task->getModelRevision());
$marking = $this->markingHelper->getMarking($petrinet, $places);
$state = new State(
[],
[$transitionId],
count($task->getModelRevision()->getPlaces()),
count($task->getModelRevision()->getTransitions())
Expand Down Expand Up @@ -93,10 +94,6 @@ protected function update(StateInterface $state, MarkingInterface $marking, int
}
}
$state->addVisitedTransition($transitionId);

// Update current coverage.
$state->setTransitionCoverage(count($state->getVisitedTransitions()) / $state->getTotalTransitions() * 100);
$state->setPlaceCoverage(count($state->getVisitedPlaces()) / $state->getTotalPlaces() * 100);
}

protected function nextTransition(PetrinetInterface $petrinet, MarkingInterface $marking): ?TransitionInterface
Expand Down
2 changes: 1 addition & 1 deletion src/Model/Bug.php
Expand Up @@ -5,7 +5,7 @@
use DateTimeInterface;
use Tienvx\Bundle\MbtBundle\Model\Bug\StepInterface;

abstract class Bug implements BugInterface
class Bug implements BugInterface
{
protected ?int $id = null;
protected string $title;
Expand Down
82 changes: 16 additions & 66 deletions src/Model/Generator/State.php
Expand Up @@ -2,104 +2,54 @@

namespace Tienvx\Bundle\MbtBundle\Model\Generator;

use Tienvx\Bundle\MbtBundle\Exception\OutOfRangeException;

class State implements StateInterface
{
protected array $visitedPlaces = [];
protected int $totalPlaces;
protected array $visitedTransitions = [];
protected int $totalTransitions;
protected float $transitionCoverage = 0;
protected float $placeCoverage = 0;
protected float $transitionCoverage = 1;
protected float $placeCoverage = 1;

public function __construct(
array $visitedTransitions,
int $totalPlaces,
int $totalTransitions
protected array $visitedPlaces = [],
protected array $visitedTransitions = [],
protected int $totalPlaces = 1,
protected int $totalTransitions = 1
) {
$this->visitedTransitions = $visitedTransitions;
$this->totalPlaces = $totalPlaces;
$this->totalTransitions = $totalTransitions;
}

public function getVisitedPlaces(): array
{
return $this->visitedPlaces;
}

public function setVisitedPlaces(array $visitedPlaces): void
{
$this->visitedPlaces = [];

foreach ($visitedPlaces as $visitedPlace) {
$this->addVisitedPlace($visitedPlace);
if ($totalPlaces <= 0 || $totalTransitions <= 0) {
throw new OutOfRangeException('State need at least 1 place and 1 transition');
}
$this->updateCoverage();
}

public function addVisitedPlace(int $placeId)
{
if (!in_array($placeId, $this->visitedPlaces)) {
$this->visitedPlaces[] = $placeId;
}
}

public function getTotalPlaces(): int
{
return $this->totalPlaces;
}

public function setTotalPlaces(int $totalPlaces): void
{
$this->totalPlaces = $totalPlaces;
}

public function getVisitedTransitions(): array
{
return $this->visitedTransitions;
}

public function setVisitedTransitions(array $visitedTransitions): void
{
$this->visitedTransitions = [];

foreach ($visitedTransitions as $visitedTransition) {
$this->addVisitedTransition($visitedTransition);
$this->updateCoverage();
}
}

public function addVisitedTransition(int $transitionId)
{
if (!in_array($transitionId, $this->visitedTransitions)) {
$this->visitedTransitions[] = $transitionId;
$this->updateCoverage();
}
}

public function getTotalTransitions(): int
{
return $this->totalTransitions;
}

public function setTotalTransitions(int $totalTransitions): void
{
$this->totalTransitions = $totalTransitions;
}

public function getTransitionCoverage(): float
{
return $this->transitionCoverage;
}

public function setTransitionCoverage(float $transitionCoverage): void
{
$this->transitionCoverage = $transitionCoverage;
}

public function getPlaceCoverage(): float
{
return $this->placeCoverage;
}

public function setPlaceCoverage(float $placeCoverage): void
protected function updateCoverage(): void
{
$this->placeCoverage = $placeCoverage;
$this->transitionCoverage = count($this->visitedTransitions) / $this->totalTransitions * 100;
$this->placeCoverage = count($this->visitedPlaces) / $this->totalPlaces * 100;
}
}
20 changes: 0 additions & 20 deletions src/Model/Generator/StateInterface.php
Expand Up @@ -4,31 +4,11 @@

interface StateInterface
{
public function getVisitedPlaces(): array;

public function setVisitedPlaces(array $visitedPlaces): void;

public function addVisitedPlace(int $placeId);

public function getTotalPlaces(): int;

public function setTotalPlaces(int $totalPlaces): void;

public function getVisitedTransitions(): array;

public function setVisitedTransitions(array $visitedTransitions): void;

public function addVisitedTransition(int $transitionId);

public function getTotalTransitions(): int;

public function setTotalTransitions(int $totalTransitions): void;

public function getTransitionCoverage(): float;

public function setTransitionCoverage(float $transitionCoverage): void;

public function getPlaceCoverage(): float;

public function setPlaceCoverage(float $placeCoverage): void;
}
8 changes: 7 additions & 1 deletion src/Model/Task.php
Expand Up @@ -3,6 +3,7 @@
namespace Tienvx\Bundle\MbtBundle\Model;

use DateTimeInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Tienvx\Bundle\MbtBundle\Model\Model\RevisionInterface;
use Tienvx\Bundle\MbtBundle\Model\Task\BrowserInterface;
Expand All @@ -20,6 +21,11 @@ class Task implements TaskInterface
protected DateTimeInterface $updatedAt;
protected DateTimeInterface $createdAt;

public function __construct()
{
$this->bugs = new ArrayCollection();
}

public function setId(int $id)
{
$this->id = $id;
Expand Down Expand Up @@ -81,7 +87,7 @@ public function setBrowser(BrowserInterface $browser): void
}

/**
* @return Collection|BugInterface[]
* @return Collection<BugInterface>
*/
public function getBugs(): Collection
{
Expand Down
5 changes: 1 addition & 4 deletions src/Reducer/DispatcherTemplate.php
Expand Up @@ -33,10 +33,7 @@ public function dispatch(BugInterface $bug): int
return count($pairs);
}

protected function getPairs(array $steps): array
{
return [];
}
abstract protected function getPairs(array $steps): array;

protected function maxPairs(array $steps): int
{
Expand Down
1 change: 1 addition & 0 deletions src/Resources/translations/validators.en.php
Expand Up @@ -3,6 +3,7 @@
return [
'mbt' => [
'model' => [
'missing_places' => 'Places are missing.',
'places_invalid' => 'Places are invalid.',
'missing_start_transition' => 'Missing start transition.',
'too_many_start_transitions' => 'There must be only one start transition.',
Expand Down
47 changes: 33 additions & 14 deletions tests/Entity/BugTest.php
Expand Up @@ -2,43 +2,62 @@

namespace Tienvx\Bundle\MbtBundle\Tests\Entity;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Validator\Validation;
use Tienvx\Bundle\MbtBundle\Entity\Bug;
use Tienvx\Bundle\MbtBundle\Model\BugInterface;
use Tienvx\Bundle\MbtBundle\Tests\Model\BugTest as BugModelTest;

/**
* @covers \Tienvx\Bundle\MbtBundle\Entity\Bug
* @covers \Tienvx\Bundle\MbtBundle\Model\Bug
*
* @uses \Tienvx\Bundle\MbtBundle\Entity\Task
* @uses \Tienvx\Bundle\MbtBundle\Model\Task
* @uses \Tienvx\Bundle\MbtBundle\ValueObject\Bug\Step
* @uses \Tienvx\Bundle\MbtBundle\Model\Bug\Step
* @uses \Tienvx\Bundle\MbtBundle\Entity\Progress
* @uses \Tienvx\Bundle\MbtBundle\Model\Progress
*/
class BugTest extends TestCase
class BugTest extends BugModelTest
{
public function testPrePersist(): void
{
$bug = new Bug();
$bug->prePersist();
$this->assertInstanceOf(\DateTime::class, $bug->getCreatedAt());
$this->assertInstanceOf(\DateTime::class, $bug->getUpdatedAt());
$this->bug->prePersist();
$this->assertInstanceOf(\DateTime::class, $this->bug->getCreatedAt());
$this->assertInstanceOf(\DateTime::class, $this->bug->getUpdatedAt());
}

public function testPreUpdate(): void
{
$bug = new Bug();
$bug->prePersist();
$bug->preUpdate();
$this->assertInstanceOf(\DateTime::class, $bug->getUpdatedAt());
$this->bug->prePersist();
$this->bug->preUpdate();
$this->assertInstanceOf(\DateTime::class, $updatedAt = $this->bug->getUpdatedAt());
$this->bug->preUpdate();
$this->assertTrue(
$this->bug->getUpdatedAt() instanceof \DateTime
&& $updatedAt !== $this->bug->getUpdatedAt()
);
}

public function testValidateInvalidBug(): void
{
$bug = new Bug();
$bug->setTitle('');
$this->bug->setTitle('');

$validator = Validation::createValidatorBuilder()->enableAnnotationMapping()->getValidator();
$violations = $validator->validate($bug);
$this->assertCount(1, $violations);
$violations = $validator->validate($this->bug);
$this->assertCount(3, $violations);
$message = 'Object(Tienvx\Bundle\MbtBundle\Entity\Bug).title:
This value should not be blank. (code c1051bb4-d103-4f74-8988-acbcafc7fdc3)
Object(Tienvx\Bundle\MbtBundle\Entity\Bug).steps[0].places:
mbt.bug.missing_places_in_step (code bef8e338-6ae5-4caf-b8e2-50e7b0579e69)
Object(Tienvx\Bundle\MbtBundle\Entity\Bug).steps[1].places:
mbt.bug.missing_places_in_step (code bef8e338-6ae5-4caf-b8e2-50e7b0579e69)
';
$this->assertSame($message, (string) $violations);
}

protected function createBug(): BugInterface
{
return new Bug();
}
}

0 comments on commit 31bdf06

Please sign in to comment.