Skip to content

Commit cd3dbc7

Browse files
committed
1 parent b30ec27 commit cd3dbc7

3 files changed

Lines changed: 142 additions & 110 deletions

File tree

app/controllers/assignments_controller.rb

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -270,28 +270,41 @@ def summary
270270
end
271271

272272
def download_test_results
273+
@assignment = record
273274
latest = params[:latest] == 'true'
274275

275-
@assignment = record
276+
test_results = SummaryTestResultsHelper::SummaryTestResults.fetch(
277+
test_groups: @assignment.test_groups,
278+
latest:
279+
)
280+
276281
respond_to do |format|
277282
format.json do
278-
data = @assignment.summary_test_result_json(latest:)
283+
data = test_results.as_json
284+
279285
zip_path = "tmp/#{@assignment.short_identifier}_test_results.zip"
280286
Zip::File.open(zip_path, create: true) do |zip_file|
281287
zip_file.get_output_stream('test_results.json') do |f|
282288
f.write(data)
283289
end
284290
end
285-
send_file zip_path, disposition: 'inline',
286-
filename: "#{@assignment.short_identifier}_test_results.zip"
291+
292+
send_file(
293+
zip_path,
294+
disposition: 'inline',
295+
filename: "#{@assignment.short_identifier}_test_results.zip"
296+
)
287297
end
298+
288299
format.csv do
289-
data = @assignment.summary_test_result_csv
290300
filename = "#{@assignment.short_identifier}_test_results.csv"
291-
send_data data,
292-
disposition: 'attachment',
293-
type: 'text/csv',
294-
filename: filename
301+
302+
send_data(
303+
test_results.as_csv,
304+
disposition: 'attachment',
305+
type: 'text/csv',
306+
filename: filename
307+
)
295308
end
296309
end
297310
end
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
module SummaryTestResultsHelper
2+
class SummaryTestResults
3+
class << self
4+
def fetch(test_groups:, latest:)
5+
latest ? fetch_latest(test_groups:) : fetch_all(test_groups:)
6+
end
7+
8+
private
9+
10+
def fetch_all(test_groups:)
11+
latest_test_run_by_grouping = TestRun.select('created_at as test_runs_created_at',
12+
'grouping_id')
13+
.where.not(submission_id: nil)
14+
.to_sql
15+
16+
latest_test_runs = TestRun
17+
.joins(grouping: :group)
18+
.joins("INNER JOIN (#{latest_test_run_by_grouping}) latest_test_run_by_grouping \
19+
ON latest_test_run_by_grouping.grouping_id = test_runs.grouping_id \
20+
AND latest_test_run_by_grouping.test_runs_created_at = test_runs.created_at")
21+
.select('id', 'test_runs.grouping_id', 'groups.group_name')
22+
.to_sql
23+
24+
test_results = test_groups.joins(test_group_results: :test_results)
25+
.joins("INNER JOIN (#{latest_test_runs}) latest_test_runs \
26+
ON test_group_results.test_run_id = latest_test_runs.id")
27+
.select('test_groups.name',
28+
'test_groups.id as test_groups_id',
29+
'latest_test_runs.group_name',
30+
'test_results.name as test_result_name',
31+
'test_results.status',
32+
'test_results.marks_earned',
33+
'test_results.marks_total',
34+
:output, :extra_info, :error_type)
35+
36+
SummaryTestResult.new(test_results:)
37+
end
38+
39+
def fetch_latest(test_groups:)
40+
latest_test_run_by_grouping = TestRun.group('grouping_id').select('MAX(created_at) as test_runs_created_at',
41+
'grouping_id')
42+
.where.not(submission_id: nil)
43+
.to_sql
44+
45+
latest_test_runs = TestRun
46+
.joins(grouping: :group)
47+
.joins("INNER JOIN (#{latest_test_run_by_grouping}) latest_test_run_by_grouping \
48+
ON latest_test_run_by_grouping.grouping_id = test_runs.grouping_id \
49+
AND latest_test_run_by_grouping.test_runs_created_at = test_runs.created_at")
50+
.select('id', 'test_runs.grouping_id', 'groups.group_name')
51+
.to_sql
52+
53+
test_results = test_groups.joins(test_group_results: :test_results)
54+
.joins("INNER JOIN (#{latest_test_runs}) latest_test_runs \
55+
ON test_group_results.test_run_id = latest_test_runs.id")
56+
.select('test_groups.name',
57+
'test_groups.id as test_groups_id',
58+
'latest_test_runs.group_name',
59+
'test_results.name as test_result_name',
60+
'test_results.status',
61+
'test_results.marks_earned',
62+
'test_results.marks_total',
63+
:output, :extra_info, :error_type)
64+
65+
SummaryTestResult.new(test_results:)
66+
end
67+
end
68+
69+
70+
end
71+
72+
class SummaryTestResult
73+
def initialize(test_results:)
74+
@test_results = test_results
75+
end
76+
77+
def as_csv
78+
results = {}
79+
headers = Set.new
80+
81+
summary_test_results = @test_results.as_json
82+
83+
summary_test_results.each do |test_result|
84+
header = "#{test_result['name']}:#{test_result['test_result_name']}"
85+
86+
if results.key?(test_result['group_name'])
87+
results[test_result['group_name']][header] = test_result['status']
88+
else
89+
results[test_result['group_name']] = { header => test_result['status'] }
90+
end
91+
92+
headers << header
93+
end
94+
headers = headers.sort
95+
96+
CSV.generate do |csv|
97+
csv << [nil, *headers]
98+
99+
results.sort_by(&:first).each do |(group_name, _test_group)|
100+
row = [group_name]
101+
102+
headers.each do |header|
103+
if results[group_name].key?(header)
104+
row << results[group_name][header]
105+
else
106+
row << nil
107+
end
108+
end
109+
csv << row
110+
end
111+
end
112+
end
113+
114+
def as_json
115+
@test_results.group_by(&:group_name).transform_values do |grouping|
116+
grouping.group_by(&:name)
117+
end.to_json
118+
end
119+
end
120+
end

app/models/assignment.rb

Lines changed: 0 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -667,107 +667,6 @@ def summary_json(user)
667667
ltiDeployments: lti_deployments }
668668
end
669669

670-
# Generates the summary of the most test results associated with an assignment.
671-
def summary_test_results
672-
latest_test_run_by_grouping = TestRun.select('created_at as test_runs_created_at',
673-
'grouping_id')
674-
.where.not(submission_id: nil)
675-
.to_sql
676-
677-
latest_test_runs = TestRun
678-
.joins(grouping: :group)
679-
.joins("INNER JOIN (#{latest_test_run_by_grouping}) latest_test_run_by_grouping \
680-
ON latest_test_run_by_grouping.grouping_id = test_runs.grouping_id \
681-
AND latest_test_run_by_grouping.test_runs_created_at = test_runs.created_at")
682-
.select('id', 'test_runs.grouping_id', 'groups.group_name')
683-
.to_sql
684-
685-
self.test_groups.joins(test_group_results: :test_results)
686-
.joins("INNER JOIN (#{latest_test_runs}) latest_test_runs \
687-
ON test_group_results.test_run_id = latest_test_runs.id")
688-
.select('test_groups.name',
689-
'test_groups.id as test_groups_id',
690-
'latest_test_runs.group_name',
691-
'test_results.name as test_result_name',
692-
'test_results.status',
693-
'test_results.marks_earned',
694-
'test_results.marks_total',
695-
:output, :extra_info, :error_type)
696-
end
697-
698-
def latest_summary_test_results
699-
latest_test_run_by_grouping = TestRun.group('grouping_id').select('MAX(created_at) as test_runs_created_at',
700-
'grouping_id')
701-
.where.not(submission_id: nil)
702-
.to_sql
703-
704-
latest_test_runs = TestRun
705-
.joins(grouping: :group)
706-
.joins("INNER JOIN (#{latest_test_run_by_grouping}) latest_test_run_by_grouping \
707-
ON latest_test_run_by_grouping.grouping_id = test_runs.grouping_id \
708-
AND latest_test_run_by_grouping.test_runs_created_at = test_runs.created_at")
709-
.select('id', 'test_runs.grouping_id', 'groups.group_name')
710-
.to_sql
711-
712-
self.test_groups.joins(test_group_results: :test_results)
713-
.joins("INNER JOIN (#{latest_test_runs}) latest_test_runs \
714-
ON test_group_results.test_run_id = latest_test_runs.id")
715-
.select('test_groups.name',
716-
'test_groups.id as test_groups_id',
717-
'latest_test_runs.group_name',
718-
'test_results.name as test_result_name',
719-
'test_results.status',
720-
'test_results.marks_earned',
721-
'test_results.marks_total',
722-
:output, :extra_info, :error_type)
723-
end
724-
725-
# Generate a JSON summary of the most recent test results associated with an assignment.
726-
def summary_test_result_json(latest: true)
727-
test_results = latest ? latest_summary_test_results : summary_test_results
728-
729-
test_results.group_by(&:group_name).transform_values do |grouping|
730-
grouping.group_by(&:name)
731-
end.to_json
732-
end
733-
734-
# Generate a CSV summary of the most recent test results associated with an assignment.
735-
def summary_test_result_csv
736-
results = {}
737-
headers = Set.new
738-
summary_test_results = self.latest_summary_test_results.as_json
739-
740-
summary_test_results.each do |test_result|
741-
header = "#{test_result['name']}:#{test_result['test_result_name']}"
742-
743-
if results.key?(test_result['group_name'])
744-
results[test_result['group_name']][header] = test_result['status']
745-
else
746-
results[test_result['group_name']] = { header => test_result['status'] }
747-
end
748-
749-
headers << header
750-
end
751-
headers = headers.sort
752-
753-
CSV.generate do |csv|
754-
csv << [nil, *headers]
755-
756-
results.sort_by(&:first).each do |(group_name, _test_group)|
757-
row = [group_name]
758-
759-
headers.each do |header|
760-
if results[group_name].key?(header)
761-
row << results[group_name][header]
762-
else
763-
row << nil
764-
end
765-
end
766-
csv << row
767-
end
768-
end
769-
end
770-
771670
# Generate CSV summary of grades for this assignment
772671
# for the current user. The user should be an instructor or TA.
773672
def summary_csv(role)

0 commit comments

Comments
 (0)