Skip to content

Commit ec8e634

Browse files
committed
test: add interface and adapter for Scraper to enable mocking in unit tests
1 parent 3b4c9a0 commit ec8e634

File tree

4 files changed

+136
-6
lines changed

4 files changed

+136
-6
lines changed

scraper.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use BOA\Programs\ProgramScraper;
88
use BOA\Programs\ProgramStorage;
9+
use BOA\Programs\ScraperAdapter;
910
use BVP\Scraper\Scraper;
1011
use Carbon\CarbonImmutable as Carbon;
1112

@@ -17,9 +18,9 @@
1718

1819
// v2 の場合のみ ProgramScraper を利用して出走表データを取得
1920
if ($version === 'v2') {
20-
$scraper = new ProgramScraper(
21-
Scraper::getInstance()
22-
);
21+
$scraperInstance = Scraper::getInstance();
22+
$scraperAdapter = new ScraperAdapter($scraperInstance);
23+
$scraper = new ProgramScraper($scraperAdapter);
2324

2425
// 指定日付の出走表データをスクレイピング
2526
$programs = $scraper->scrape($date);

src/ProgramScraper.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
namespace BOA\Programs;
66

7-
use BVP\Scraper\Scraper;
87
use Carbon\CarbonImmutable as Carbon;
98
use Carbon\CarbonInterface;
109

@@ -14,9 +13,9 @@
1413
final class ProgramScraper
1514
{
1615
/**
17-
* @param \BVP\Scraper\Scraper $scraper
16+
* @param \BOA\Programs\ScraperInterface $scraper
1817
*/
19-
public function __construct(private readonly Scraper $scraper)
18+
public function __construct(private readonly ScraperInterface $scraper)
2019
{
2120
//
2221
}

src/ScraperAdapter.php

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace BOA\Programs;
6+
7+
use BVP\Scraper\Scraper;
8+
use Carbon\CarbonInterface;
9+
10+
/**
11+
* @author shimomo
12+
*/
13+
final class ScraperAdapter implements ScraperInterface
14+
{
15+
/**
16+
* @param \BVP\Scraper\Scraper $scraper
17+
*/
18+
public function __construct(private readonly Scraper $scraper)
19+
{
20+
//
21+
}
22+
23+
/**
24+
* @psalm-type ScrapedBoat = array{
25+
* racer_boat_number: int,
26+
* racer_name: string,
27+
* racer_number: int,
28+
* racer_class_number: int,
29+
* racer_branch_number: int,
30+
* racer_birthplace_number: int,
31+
* racer_age: int,
32+
* racer_weight: float,
33+
* racer_flying_count: int,
34+
* racer_late_count: int,
35+
* racer_average_start_timing: float,
36+
* racer_national_top_1_percent: float,
37+
* racer_national_top_2_percent: float,
38+
* racer_national_top_3_percent: float,
39+
* racer_local_top_1_percent: float,
40+
* racer_local_top_2_percent: float,
41+
* racer_local_top_3_percent: float,
42+
* racer_assigned_motor_number: int,
43+
* racer_assigned_motor_top_2_percent: float,
44+
* racer_assigned_motor_top_3_percent: float,
45+
* racer_assigned_boat_number: int,
46+
* racer_assigned_boat_top_2_percent: float,
47+
* racer_assigned_boat_top_3_percent: float
48+
* }
49+
* @psalm-type ScrapedRace = array{
50+
* race_date: string,
51+
* race_stadium_number: int,
52+
* race_number: int,
53+
* race_closed_at: string,
54+
* race_grade_number: int,
55+
* race_title: string,
56+
* race_subtitle: string,
57+
* race_distance: int,
58+
* boats: array<int, ScrapedBoat>
59+
* }
60+
* @psalm-type ScrapedRaces = array<int, ScrapedRace>
61+
* @psalm-type ScrapedStadiumRaces = array<int, ScrapedRaces>
62+
*
63+
* @param \Carbon\CarbonInterface $date
64+
* @return ScrapedStadiumRaces
65+
*/
66+
#[\Override]
67+
public function scrapePrograms(CarbonInterface $date): array
68+
{
69+
/** @psalm-var ScrapedStadiumRaces */
70+
return $this->scraper->scrapePrograms($date);
71+
}
72+
}

src/ScraperInterface.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace BOA\Programs;
6+
7+
use Carbon\CarbonInterface;
8+
9+
/**
10+
* @author shimomo
11+
*/
12+
interface ScraperInterface
13+
{
14+
/**
15+
* @psalm-type ScrapedBoat = array{
16+
* racer_boat_number: int,
17+
* racer_name: string,
18+
* racer_number: int,
19+
* racer_class_number: int,
20+
* racer_branch_number: int,
21+
* racer_birthplace_number: int,
22+
* racer_age: int,
23+
* racer_weight: float,
24+
* racer_flying_count: int,
25+
* racer_late_count: int,
26+
* racer_average_start_timing: float,
27+
* racer_national_top_1_percent: float,
28+
* racer_national_top_2_percent: float,
29+
* racer_national_top_3_percent: float,
30+
* racer_local_top_1_percent: float,
31+
* racer_local_top_2_percent: float,
32+
* racer_local_top_3_percent: float,
33+
* racer_assigned_motor_number: int,
34+
* racer_assigned_motor_top_2_percent: float,
35+
* racer_assigned_motor_top_3_percent: float,
36+
* racer_assigned_boat_number: int,
37+
* racer_assigned_boat_top_2_percent: float,
38+
* racer_assigned_boat_top_3_percent: float
39+
* }
40+
* @psalm-type ScrapedRace = array{
41+
* race_date: string,
42+
* race_stadium_number: int,
43+
* race_number: int,
44+
* race_closed_at: string,
45+
* race_grade_number: int,
46+
* race_title: string,
47+
* race_subtitle: string,
48+
* race_distance: int,
49+
* boats: array<int, ScrapedBoat>
50+
* }
51+
* @psalm-type ScrapedRaces = array<int, ScrapedRace>
52+
* @psalm-type ScrapedStadiumRaces = array<int, ScrapedRaces>
53+
*
54+
* @param \Carbon\CarbonInterface $date
55+
* @return ScrapedStadiumRaces
56+
*/
57+
public function scrapePrograms(CarbonInterface $date): array;
58+
}

0 commit comments

Comments
 (0)