Skip to content

Commit f37f29e

Browse files
committed
feat: tests
1 parent f3be78d commit f37f29e

File tree

10 files changed

+862
-22
lines changed

10 files changed

+862
-22
lines changed

phpunit.xml

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,13 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" backupGlobals="false" bootstrap="vendor/autoload.php"
3-
colors="true" processIsolation="false" stopOnFailure="false"
4-
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/11.0/phpunit.xsd" cacheDirectory=".phpunit.cache"
5-
backupStaticProperties="false">
6-
<testsuites>
7-
<testsuite name="Application Test Suite">
8-
<directory>./tests/</directory>
9-
</testsuite>
10-
</testsuites>
11-
<php>
12-
<env name="APP_KEY" value="AckfSECXIvnK5r28GVIWUAxmbBSjTsmF"/>
13-
<env name="APP_DEBUG" value="true"/>
14-
<env name="OTLE_TRACE_ENDPOINT" value="http://localhost:4318/v1/traces"/>
15-
</php>
16-
<source>
17-
<include>
18-
<directory suffix=".php">src/</directory>
19-
</include>
20-
</source>
2+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd" bootstrap="vendor/autoload.php" colors="true" stopOnFailure="false" cacheDirectory=".phpunit.cache">
3+
<testsuites>
4+
<testsuite name="Laravel OpenTelemetry Test Suite">
5+
<directory suffix="Test.php">./tests</directory>
6+
</testsuite>
7+
</testsuites>
8+
<source>
9+
<include>
10+
<directory suffix=".php">./src</directory>
11+
</include>
12+
</source>
2113
</phpunit>

src/Console/Commands/TestCommand.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ public function handle(): int
2525
{
2626
$this->info('Creating test span...');
2727

28+
if (! config('otel.enabled')) {
29+
$this->info('OpenTelemetry is disabled.');
30+
31+
return Command::SUCCESS;
32+
}
33+
2834
// Create root span
2935
$rootSpan = Measure::start('Test Span');
3036
$rootSpan->span->setAttribute('test.attribute', 'test_value');
@@ -58,17 +64,17 @@ public function handle(): int
5864

5965
// Output result
6066
$this->info('Test completed!');
61-
$this->info('Trace ID: ' . $traceId);
67+
$this->info('Trace ID: '.$traceId);
6268

6369
// Display information table
6470
$this->table(
6571
['Span Name', 'Status', 'Attributes'],
6672
[
67-
['Test Span', 'OK', 'test.attribute=test_value, timestamp=' . $rootSpan->span->getAttribute('timestamp')],
73+
['Test Span', 'OK', 'test.attribute=test_value, timestamp='.$rootSpan->span->getAttribute('timestamp')],
6874
['Child Operation', 'OK', 'child.attribute=child_value'],
6975
]
7076
);
7177

7278
return Command::SUCCESS;
7379
}
74-
}
80+
}
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
<?php
2+
3+
namespace Overtrue\LaravelOpenTelemetry\Tests\Console\Commands;
4+
5+
use Illuminate\Support\Facades\Artisan;
6+
use Mockery;
7+
use OpenTelemetry\API\Trace\SpanBuilderInterface;
8+
use OpenTelemetry\API\Trace\SpanContextInterface;
9+
use OpenTelemetry\API\Trace\SpanInterface;
10+
use OpenTelemetry\API\Trace\StatusCode;
11+
use OpenTelemetry\API\Trace\TracerInterface;
12+
use OpenTelemetry\Context\ScopeInterface;
13+
use Overtrue\LaravelOpenTelemetry\Facades\Measure;
14+
use Overtrue\LaravelOpenTelemetry\Support\StartedSpan;
15+
use Overtrue\LaravelOpenTelemetry\Tests\TestCase;
16+
17+
class TestCommandTest extends TestCase
18+
{
19+
protected function setUp(): void
20+
{
21+
parent::setUp();
22+
23+
// 确保 OpenTelemetry 已启用
24+
config(['otel.enabled' => true]);
25+
26+
// Mock Tracer
27+
$tracer = Mockery::mock(TracerInterface::class);
28+
$spanBuilder = Mockery::mock(SpanBuilderInterface::class);
29+
$span = Mockery::mock(SpanInterface::class);
30+
$spanContext = Mockery::mock(SpanContextInterface::class);
31+
$scope = Mockery::mock(ScopeInterface::class);
32+
$status = Mockery::mock('status');
33+
$status->shouldReceive('getCode')->andReturn(StatusCode::STATUS_OK);
34+
35+
// 设置 span 的期望行为
36+
$span->shouldReceive('setAttribute')->andReturnSelf();
37+
$span->shouldReceive('addEvent')->andReturnSelf();
38+
$span->shouldReceive('setStatus')->andReturnSelf();
39+
$span->shouldReceive('getContext')->andReturn($spanContext);
40+
$span->shouldReceive('getAttribute')->andReturn('test_value');
41+
$span->shouldReceive('end')->andReturnSelf();
42+
$span->shouldReceive('activate')->andReturn($scope);
43+
$span->shouldReceive('getStatus')->andReturn($status);
44+
45+
// 设置 span context 的期望行为
46+
$spanContext->shouldReceive('getTraceId')->andReturn('test-trace-id');
47+
48+
// 设置 span builder 的期望行为
49+
$spanBuilder->shouldReceive('start')->andReturn($span);
50+
51+
// 设置 tracer 的期望行为
52+
$tracer->shouldReceive('spanBuilder')->andReturn($spanBuilder);
53+
54+
// 替换 Measure facade 的 tracer
55+
Measure::shouldReceive('tracer')->andReturn($tracer);
56+
Measure::shouldReceive('activeSpan')->andReturn($span);
57+
Measure::shouldReceive('start')->andReturn(new StartedSpan($span, $scope));
58+
Measure::shouldReceive('end')->andReturnNull();
59+
}
60+
61+
public function test_command_creates_test_span()
62+
{
63+
// 执行命令
64+
$result = Artisan::call('otel:test');
65+
66+
// 验证命令执行成功
67+
$this->assertEquals(0, $result);
68+
69+
// 验证输出包含预期的信息
70+
$output = Artisan::output();
71+
$this->assertStringContainsString('Creating test span...', $output);
72+
$this->assertStringContainsString('Test completed!', $output);
73+
$this->assertStringContainsString('Trace ID:', $output);
74+
}
75+
76+
public function test_command_creates_span_with_correct_attributes()
77+
{
78+
// 执行命令
79+
Artisan::call('otel:test');
80+
81+
// 获取当前活动的 span
82+
$span = Measure::activeSpan();
83+
84+
// 验证 span 属性
85+
$this->assertEquals('test_value', $span->getAttribute('test.attribute'));
86+
}
87+
88+
public function test_command_creates_child_span()
89+
{
90+
// 执行命令
91+
Artisan::call('otel:test');
92+
93+
// 获取当前活动的 span
94+
$span = Measure::activeSpan();
95+
96+
// 验证子 span 属性
97+
$this->assertEquals('test_value', $span->getAttribute('child.attribute'));
98+
}
99+
100+
public function test_command_sets_correct_status()
101+
{
102+
// 执行命令
103+
Artisan::call('otel:test');
104+
105+
// 获取当前活动的 span
106+
$span = Measure::activeSpan();
107+
108+
// 验证状态
109+
$this->assertEquals(StatusCode::STATUS_OK, $span->getStatus()->getCode());
110+
}
111+
112+
public function test_command_outputs_correct_table()
113+
{
114+
// 执行命令
115+
Artisan::call('otel:test');
116+
117+
// 获取输出
118+
$output = Artisan::output();
119+
120+
// 验证表格输出
121+
$this->assertStringContainsString('Span Name', $output);
122+
$this->assertStringContainsString('Status', $output);
123+
$this->assertStringContainsString('Attributes', $output);
124+
$this->assertStringContainsString('Test Span', $output);
125+
$this->assertStringContainsString('Child Operation', $output);
126+
}
127+
128+
public function test_command_handles_otel_disabled()
129+
{
130+
// 禁用 OpenTelemetry
131+
config(['otel.enabled' => false]);
132+
133+
// 清除所有 mock
134+
Mockery::close();
135+
136+
// 重新设置 mock,但这次 Measure facade 的所有方法都返回 null
137+
Measure::shouldReceive('tracer')->andReturnNull();
138+
Measure::shouldReceive('activeSpan')->andReturnNull();
139+
Measure::shouldReceive('start')->andReturnNull();
140+
Measure::shouldReceive('end')->andReturnNull();
141+
142+
// 执行命令
143+
$result = Artisan::call('otel:test');
144+
145+
// 验证命令仍然执行成功
146+
$this->assertEquals(0, $result);
147+
148+
// 验证输出不包含 OpenTelemetry 相关信息
149+
$output = Artisan::output();
150+
$this->assertStringNotContainsString('Trace ID:', $output);
151+
}
152+
153+
protected function tearDown(): void
154+
{
155+
Mockery::close();
156+
parent::tearDown();
157+
}
158+
}

0 commit comments

Comments
 (0)