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+ email : 'test1@example.com' ,
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+ email : 'test2@example.com' ,
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+ email : 'test3@example.com' ,
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