80
80
expect ( result ) . to be_a ( LazyHighCharts ::HighChart )
81
81
end
82
82
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