Skip to content

Commit 54e4bdd

Browse files
committed
test: 統計グラフテストを改善
統計グラフの検証テストを複数の観点から改善。 Changes: 1. 環境非依存のテストデータ作成 - 2012-2024年の全期間でリアルなパターンのテストデータ - 153件の明示的なイベント履歴で実データパターンを再現 - CI環境でも安定動作 2. 道場数グラフの検証を追加 - 「開設数」が負にならないことを検証 - 新形式のデータ(active_dojosとnew_dojos)を使用 - 複数道場の作成と非アクティブ化をテスト 3. グラフデータへのアクセス方法を修正 - chart.options[:series] → chart.series_data に変更 - 実際のシリーズデータを正しく取得 これにより、テストが実データに近いパターンで動作し、 フレーキーテストの問題も解決される。
1 parent 2505fcf commit 54e4bdd

File tree

1 file changed

+194
-1
lines changed

1 file changed

+194
-1
lines changed

spec/models/stat_spec.rb

Lines changed: 194 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,197 @@
8080
expect(result).to be_a(LazyHighCharts::HighChart)
8181
end
8282
end
83-
end
83+
84+
describe 'グラフデータの妥当性検証' do
85+
let(:period) { Date.new(2012, 1, 1)..Date.new(2024, 12, 31) }
86+
let(:stat) { Stat.new(period) }
87+
88+
before do
89+
# テスト用のDojoを作成(複数作成して、一部を非アクティブ化)
90+
dojo1 = Dojo.create!(
91+
name: 'CoderDojo テスト1',
92+
93+
description: 'テスト用Dojo1の説明',
94+
tags: ['Scratch'],
95+
url: 'https://test1.coderdojo.jp',
96+
created_at: Time.zone.local(2012, 4, 1),
97+
prefecture_id: 13,
98+
is_active: true
99+
)
100+
101+
# 2022年に非アクティブ化される道場
102+
dojo2 = Dojo.create!(
103+
name: 'CoderDojo テスト2',
104+
105+
description: 'テスト用Dojo2の説明',
106+
tags: ['Python'],
107+
url: 'https://test2.coderdojo.jp',
108+
created_at: Time.zone.local(2019, 1, 1),
109+
prefecture_id: 14,
110+
is_active: false,
111+
inactivated_at: Time.zone.local(2022, 6, 1)
112+
)
113+
114+
# 2023年に非アクティブ化される道場
115+
dojo3 = Dojo.create!(
116+
name: 'CoderDojo テスト3',
117+
118+
description: 'テスト用Dojo3の説明',
119+
tags: ['Ruby'],
120+
url: 'https://test3.coderdojo.jp',
121+
created_at: Time.zone.local(2020, 1, 1),
122+
prefecture_id: 27,
123+
is_active: false,
124+
inactivated_at: Time.zone.local(2023, 3, 1)
125+
)
126+
127+
# テスト用のイベント履歴を作成(実際のデータパターンに近づける)
128+
# 成長曲線を再現:初期は少なく、徐々に増加、COVID後に減少、その後回復
129+
test_data = {
130+
2012 => { events: 2, participants_per_event: 4 }, # 創成期
131+
2013 => { events: 3, participants_per_event: 4 }, # 徐々に増加
132+
2014 => { events: 5, participants_per_event: 5 },
133+
2015 => { events: 6, participants_per_event: 6 },
134+
2016 => { events: 8, participants_per_event: 6 },
135+
2017 => { events: 12, participants_per_event: 7 }, # 成長期
136+
2018 => { events: 15, participants_per_event: 7 },
137+
2019 => { events: 20, participants_per_event: 8 }, # ピーク
138+
2020 => { events: 16, participants_per_event: 5 }, # COVID影響
139+
2021 => { events: 14, participants_per_event: 4 }, # 低迷継続
140+
2022 => { events: 16, participants_per_event: 5 }, # 回復開始
141+
2023 => { events: 18, participants_per_event: 6 }, # 回復継続
142+
2024 => { events: 18, participants_per_event: 6 } # 安定
143+
}
144+
145+
test_data.each do |year, data|
146+
data[:events].times do |i|
147+
# dojo1のイベント(継続的に活動)
148+
EventHistory.create!(
149+
dojo_id: dojo1.id,
150+
dojo_name: dojo1.name,
151+
service_name: 'connpass',
152+
event_id: "test_#{year}_#{i}",
153+
event_url: "https://test.connpass.com/event/#{year}_#{i}/",
154+
evented_at: Date.new(year, 3, 1) + (i * 2).weeks,
155+
participants: data[:participants_per_event]
156+
)
157+
end
158+
end
159+
end
160+
161+
it '開催回数のグラフに負の値が含まれないこと' do
162+
# テストデータから集計
163+
event_data = stat.annual_count_of_event_histories
164+
165+
# 各年の開催回数が0以上であることを確認
166+
event_data.each do |year, count|
167+
expect(count).to be >= 0, "#{year}年の開催回数が負の値です: #{count}"
168+
end
169+
170+
# 期待される値を確認(明示的なテストデータに基づく)
171+
# annual_count_of_event_historiesは文字列キーを返す
172+
expect(event_data['2012']).to eq(2)
173+
expect(event_data['2013']).to eq(3)
174+
expect(event_data['2014']).to eq(5)
175+
expect(event_data['2015']).to eq(6)
176+
expect(event_data['2016']).to eq(8)
177+
expect(event_data['2017']).to eq(12)
178+
expect(event_data['2018']).to eq(15)
179+
expect(event_data['2019']).to eq(20)
180+
expect(event_data['2020']).to eq(16)
181+
expect(event_data['2021']).to eq(14)
182+
expect(event_data['2022']).to eq(16)
183+
expect(event_data['2023']).to eq(18)
184+
expect(event_data['2024']).to eq(18)
185+
186+
# グラフデータを生成
187+
chart = HighChartsBuilder.build_annual_event_histories(event_data)
188+
series_data = chart.series_data
189+
190+
if series_data
191+
# 年間の開催回数(棒グラフ)が負でないことを確認
192+
annual_counts = series_data.find { |s| s[:type] == 'column' }
193+
if annual_counts && annual_counts[:data]
194+
annual_counts[:data].each_with_index do |count, i|
195+
year = 2012 + i # テストデータの開始年は2012
196+
expect(count).to be >= 0, "#{year}年の開催回数が負の値としてグラフに表示されます: #{count}"
197+
end
198+
end
199+
end
200+
end
201+
202+
it '参加者数のグラフに負の値が含まれないこと' do
203+
# テストデータから集計
204+
participant_data = stat.annual_sum_of_participants
205+
206+
# 各年の参加者数が0以上であることを確認
207+
participant_data.each do |year, count|
208+
expect(count).to be >= 0, "#{year}年の参加者数が負の値です: #{count}"
209+
end
210+
211+
# 期待される値を確認(明示的なテストデータに基づく)
212+
# annual_sum_of_participantsも文字列キーを返す
213+
expect(participant_data['2012']).to eq(8) # 2イベント × 4人
214+
expect(participant_data['2013']).to eq(12) # 3イベント × 4人
215+
expect(participant_data['2014']).to eq(25) # 5イベント × 5人
216+
expect(participant_data['2015']).to eq(36) # 6イベント × 6人
217+
expect(participant_data['2016']).to eq(48) # 8イベント × 6人
218+
expect(participant_data['2017']).to eq(84) # 12イベント × 7人
219+
expect(participant_data['2018']).to eq(105) # 15イベント × 7人
220+
expect(participant_data['2019']).to eq(160) # 20イベント × 8人
221+
expect(participant_data['2020']).to eq(80) # 16イベント × 5人
222+
expect(participant_data['2021']).to eq(56) # 14イベント × 4人
223+
expect(participant_data['2022']).to eq(80) # 16イベント × 5人
224+
expect(participant_data['2023']).to eq(108) # 18イベント × 6人
225+
expect(participant_data['2024']).to eq(108) # 18イベント × 6人
226+
227+
# グラフデータを生成
228+
chart = HighChartsBuilder.build_annual_participants(participant_data)
229+
series_data = chart.series_data
230+
231+
if series_data
232+
# 年間の参加者数(棒グラフ)が負でないことを確認
233+
annual_counts = series_data.find { |s| s[:type] == 'column' }
234+
if annual_counts && annual_counts[:data]
235+
annual_counts[:data].each_with_index do |count, i|
236+
year = 2012 + i # テストデータの開始年は2012
237+
expect(count).to be >= 0, "#{year}年の参加者数が負の値としてグラフに表示されます: #{count}"
238+
end
239+
end
240+
end
241+
end
242+
243+
it '道場数の「開設数」は負の値にならない(新規開設数のため)' do
244+
# 道場数のデータを取得(新しい形式)
245+
dojo_data = {
246+
active_dojos: stat.annual_dojos_with_historical_data,
247+
new_dojos: stat.annual_new_dojos_count
248+
}
249+
250+
# グラフデータを生成
251+
chart = HighChartsBuilder.build_annual_dojos(dojo_data)
252+
series_data = chart.series_data
253+
254+
if series_data
255+
# 開設数(棒グラフ)- 新規開設された道場の数
256+
change_data = series_data.find { |s| s[:type] == 'column' }
257+
if change_data && change_data[:data]
258+
change_data[:data].each_with_index do |value, i|
259+
year = 2012 + i
260+
# 「開設数」は新規開設を意味するため、負の値は論理的に不適切
261+
expect(value).to be >= 0, "#{year}年の「開設数」が負の値です: #{value}。開設数は新規開設された道場数を表すため、0以上である必要があります"
262+
end
263+
end
264+
265+
# 累積数(線グラフ)は常に0以上
266+
total_data = series_data.find { |s| s[:type] == 'line' }
267+
if total_data && total_data[:data]
268+
total_data[:data].each_with_index do |count, i|
269+
year = 2012 + i
270+
expect(count).to be >= 0, "#{year}年の累積道場数が負の値です: #{count}"
271+
end
272+
end
273+
end
274+
end
275+
end
276+
end

0 commit comments

Comments
 (0)