Skip to content

Commit 9e7e7e0

Browse files
committed
minor #452 [Platform][HuggingFace] Add tests for output classes (OskarStark)
This PR was squashed before being merged into the main branch. Discussion ---------- [Platform][HuggingFace] Add tests for output classes | Q | A | ------------- | --- | Bug fix? | no | New feature? | no | Docs? | no | Issues | -- | License | MIT Commits ------- edefe3a [Platform][HuggingFace] Add tests for output classes
2 parents a257bde + edefe3a commit 9e7e7e0

14 files changed

+1912
-30
lines changed
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\AI\Platform\Tests\Bridge\HuggingFace\Output;
13+
14+
use PHPUnit\Framework\Attributes\CoversClass;
15+
use PHPUnit\Framework\Attributes\Small;
16+
use PHPUnit\Framework\Attributes\TestDox;
17+
use PHPUnit\Framework\Attributes\TestWith;
18+
use PHPUnit\Framework\TestCase;
19+
use Symfony\AI\Platform\Bridge\HuggingFace\Output\Classification;
20+
use Symfony\AI\Platform\Bridge\HuggingFace\Output\ClassificationResult;
21+
22+
/**
23+
* @author Oskar Stark <[email protected]>
24+
*/
25+
#[CoversClass(ClassificationResult::class)]
26+
#[Small]
27+
final class ClassificationResultTest extends TestCase
28+
{
29+
#[TestDox('Construction with classifications array creates valid instance')]
30+
public function testConstruction()
31+
{
32+
$classifications = [
33+
new Classification('positive', 0.9),
34+
new Classification('negative', 0.1),
35+
];
36+
37+
$result = new ClassificationResult($classifications);
38+
39+
$this->assertSame($classifications, $result->classifications);
40+
$this->assertCount(2, $result->classifications);
41+
}
42+
43+
#[TestDox('Construction with empty array creates valid instance')]
44+
public function testConstructionWithEmptyArray()
45+
{
46+
$result = new ClassificationResult([]);
47+
48+
$this->assertSame([], $result->classifications);
49+
$this->assertCount(0, $result->classifications);
50+
}
51+
52+
#[TestDox('fromArray creates instance with Classification objects')]
53+
public function testFromArray()
54+
{
55+
$data = [
56+
['label' => 'positive', 'score' => 0.95],
57+
['label' => 'negative', 'score' => 0.03],
58+
['label' => 'neutral', 'score' => 0.02],
59+
];
60+
61+
$result = ClassificationResult::fromArray($data);
62+
63+
$this->assertCount(3, $result->classifications);
64+
65+
$this->assertSame('positive', $result->classifications[0]->label);
66+
$this->assertSame(0.95, $result->classifications[0]->score);
67+
68+
$this->assertSame('negative', $result->classifications[1]->label);
69+
$this->assertSame(0.03, $result->classifications[1]->score);
70+
71+
$this->assertSame('neutral', $result->classifications[2]->label);
72+
$this->assertSame(0.02, $result->classifications[2]->score);
73+
}
74+
75+
#[TestDox('fromArray with empty data creates empty result')]
76+
public function testFromArrayWithEmptyData()
77+
{
78+
$result = ClassificationResult::fromArray([]);
79+
80+
$this->assertCount(0, $result->classifications);
81+
$this->assertSame([], $result->classifications);
82+
}
83+
84+
#[TestDox('fromArray with single classification')]
85+
public function testFromArrayWithSingleClassification()
86+
{
87+
$data = [
88+
['label' => 'confident', 'score' => 0.99],
89+
];
90+
91+
$result = ClassificationResult::fromArray($data);
92+
93+
$this->assertCount(1, $result->classifications);
94+
$this->assertInstanceOf(Classification::class, $result->classifications[0]);
95+
$this->assertSame('confident', $result->classifications[0]->label);
96+
$this->assertSame(0.99, $result->classifications[0]->score);
97+
}
98+
99+
#[TestDox('fromArray preserves order of classifications')]
100+
public function testFromArrayPreservesOrder()
101+
{
102+
$data = [
103+
['label' => 'first', 'score' => 0.5],
104+
['label' => 'second', 'score' => 0.3],
105+
['label' => 'third', 'score' => 0.2],
106+
];
107+
108+
$result = ClassificationResult::fromArray($data);
109+
110+
$this->assertSame('first', $result->classifications[0]->label);
111+
$this->assertSame('second', $result->classifications[1]->label);
112+
$this->assertSame('third', $result->classifications[2]->label);
113+
}
114+
115+
#[TestDox('fromArray handles various label formats')]
116+
#[TestWith([['label' => '', 'score' => 0.5]])]
117+
#[TestWith([['label' => 'UPPERCASE', 'score' => 0.5]])]
118+
#[TestWith([['label' => 'with-dashes', 'score' => 0.5]])]
119+
#[TestWith([['label' => 'with_underscores', 'score' => 0.5]])]
120+
#[TestWith([['label' => 'with spaces', 'score' => 0.5]])]
121+
#[TestWith([['label' => '123numeric', 'score' => 0.5]])]
122+
public function testFromArrayWithVariousLabelFormats(array $classification)
123+
{
124+
$result = ClassificationResult::fromArray([$classification]);
125+
126+
$this->assertCount(1, $result->classifications);
127+
$this->assertSame($classification['label'], $result->classifications[0]->label);
128+
$this->assertSame($classification['score'], $result->classifications[0]->score);
129+
}
130+
}

src/platform/tests/Bridge/HuggingFace/Output/ClassificationTest.php

Lines changed: 5 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -39,43 +39,18 @@ public function testConstruction()
3939
#[TestWith(['negative', 0.01])]
4040
#[TestWith(['neutral', 0.5])]
4141
#[TestWith(['', 0.5])]
42-
#[TestWith(['this_is_a_very_long_classification_label_that_might_be_used_in_some_models', 0.75])]
43-
#[TestWith(['minimum', 0.0])]
44-
#[TestWith(['maximum', 1.0])]
4542
#[TestWith(['émoji 🎉', 0.8])]
4643
#[TestWith(['special-chars_123!@#', 0.65])]
47-
public function testConstructorWithDifferentValues(string $label, float $score)
48-
{
49-
$classification = new Classification($label, $score);
50-
51-
$this->assertSame($label, $classification->label);
52-
$this->assertSame($score, $classification->score);
53-
}
54-
55-
#[TestDox('Instance is immutable')]
56-
public function testImmutability()
57-
{
58-
$classification = new Classification('original', 0.7);
59-
60-
// Create a new instance with different values
61-
$newClassification = new Classification('modified', 0.3);
62-
63-
// Ensure original instance is unchanged
64-
$this->assertSame('original', $classification->label);
65-
$this->assertSame(0.7, $classification->score);
66-
67-
$this->assertSame('modified', $newClassification->label);
68-
$this->assertSame(0.3, $newClassification->score);
69-
}
70-
71-
#[TestDox('Special score values are handled correctly')]
44+
#[TestWith(['minimum', 0.0])]
45+
#[TestWith(['maximum', 1.0])]
7246
#[TestWith(['precision', 0.123456789])]
73-
#[TestWith(['negative', -0.5])]
47+
#[TestWith(['negative_score', -0.5])]
7448
#[TestWith(['above_one', 1.5])]
75-
public function testSpecialScoreValues(string $label, float $score)
49+
public function testConstructorWithDifferentValues(string $label, float $score)
7650
{
7751
$classification = new Classification($label, $score);
7852

53+
$this->assertSame($label, $classification->label);
7954
$this->assertSame($score, $classification->score);
8055
}
8156
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\AI\Platform\Tests\Bridge\HuggingFace\Output;
13+
14+
use PHPUnit\Framework\Attributes\CoversClass;
15+
use PHPUnit\Framework\Attributes\Small;
16+
use PHPUnit\Framework\Attributes\TestDox;
17+
use PHPUnit\Framework\Attributes\TestWith;
18+
use PHPUnit\Framework\TestCase;
19+
use Symfony\AI\Platform\Bridge\HuggingFace\Output\DetectedObject;
20+
21+
/**
22+
* @author Oskar Stark <[email protected]>
23+
*/
24+
#[CoversClass(DetectedObject::class)]
25+
#[Small]
26+
final class DetectedObjectTest extends TestCase
27+
{
28+
#[TestDox('Construction with all parameters creates valid instance')]
29+
public function testConstruction()
30+
{
31+
$object = new DetectedObject(
32+
label: 'person',
33+
score: 0.95,
34+
xmin: 10.5,
35+
ymin: 20.5,
36+
xmax: 100.5,
37+
ymax: 200.5
38+
);
39+
40+
$this->assertSame('person', $object->label);
41+
$this->assertSame(0.95, $object->score);
42+
$this->assertSame(10.5, $object->xmin);
43+
$this->assertSame(20.5, $object->ymin);
44+
$this->assertSame(100.5, $object->xmax);
45+
$this->assertSame(200.5, $object->ymax);
46+
}
47+
48+
#[TestDox('Constructor accepts various bounding box coordinates')]
49+
#[TestWith(['car', 0.88, 0.0, 0.0, 50.0, 50.0])]
50+
#[TestWith(['dog', 0.75, -10.0, -10.0, 10.0, 10.0])]
51+
#[TestWith(['tree', 0.6, 100.5, 200.5, 300.5, 400.5])]
52+
#[TestWith(['building', 0.99, 0.0, 0.0, 1920.0, 1080.0])]
53+
#[TestWith(['', 0.5, 1.0, 2.0, 3.0, 4.0])]
54+
public function testConstructorWithVariousValues(
55+
string $label,
56+
float $score,
57+
float $xmin,
58+
float $ymin,
59+
float $xmax,
60+
float $ymax,
61+
) {
62+
$object = new DetectedObject($label, $score, $xmin, $ymin, $xmax, $ymax);
63+
64+
$this->assertSame($label, $object->label);
65+
$this->assertSame($score, $object->score);
66+
$this->assertSame($xmin, $object->xmin);
67+
$this->assertSame($ymin, $object->ymin);
68+
$this->assertSame($xmax, $object->xmax);
69+
$this->assertSame($ymax, $object->ymax);
70+
}
71+
72+
#[TestDox('Constructor handles various edge cases and patterns')]
73+
#[TestWith(['person', 0.0, 0.0, 0.0, 1.0, 1.0])] // Zero score
74+
#[TestWith(['UPPERCASE_LABEL', 1.0, 0.0, 0.0, 1.0, 1.0])] // Perfect score
75+
#[TestWith(['label-with-dashes', 0.000001, 0.0, 0.0, 1.0, 1.0])] // Very low score
76+
#[TestWith(['label_with_underscores', 0.999999, 0.0, 0.0, 1.0, 1.0])] // Very high score
77+
#[TestWith(['label with spaces', 0.5, 0.0, 0.0, 1.0, 1.0])] // Space in label
78+
#[TestWith(['123', 0.8, 0.0, 0.0, 1.0, 1.0])] // Numeric label
79+
#[TestWith(['', 0.3, 0.0, 0.0, 1.0, 1.0])] // Empty label
80+
#[TestWith(['véhicule', 0.7, 0.0, 0.0, 1.0, 1.0])] // Accented characters
81+
#[TestWith(['🚗', 0.9, 0.0, 0.0, 1.0, 1.0])] // Emoji label
82+
public function testConstructorWithEdgeCasesAndPatterns(string $label, float $score, float $xmin, float $ymin, float $xmax, float $ymax)
83+
{
84+
$object = new DetectedObject($label, $score, $xmin, $ymin, $xmax, $ymax);
85+
86+
$this->assertSame($label, $object->label);
87+
$this->assertSame($score, $object->score);
88+
$this->assertSame($xmin, $object->xmin);
89+
$this->assertSame($ymin, $object->ymin);
90+
$this->assertSame($xmax, $object->xmax);
91+
$this->assertSame($ymax, $object->ymax);
92+
}
93+
94+
#[TestDox('Bounding box can represent different coordinate systems')]
95+
#[TestWith(['object', 0.9, 0.1, 0.2, 0.9, 0.8, 'normalized coordinates (0-1)'])]
96+
#[TestWith(['object', 0.9, 100.0, 200.0, 500.0, 600.0, 'pixel coordinates'])]
97+
#[TestWith(['object', 0.9, -50.0, -100.0, 50.0, 100.0, 'negative coordinates (possible in some coordinate systems)'])]
98+
public function testBoundingBoxCoordinateSystems(
99+
string $label,
100+
float $score,
101+
float $xmin,
102+
float $ymin,
103+
float $xmax,
104+
float $ymax,
105+
string $description,
106+
) {
107+
$object = new DetectedObject($label, $score, $xmin, $ymin, $xmax, $ymax);
108+
109+
$this->assertSame($xmin, $object->xmin);
110+
$this->assertSame($ymin, $object->ymin);
111+
$this->assertSame($xmax, $object->xmax);
112+
$this->assertSame($ymax, $object->ymax);
113+
}
114+
}

0 commit comments

Comments
 (0)