forked from Courseography/courseography
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCourseControllerTests.hs
More file actions
212 lines (190 loc) · 18 KB
/
CourseControllerTests.hs
File metadata and controls
212 lines (190 loc) · 18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
{-|
Description: Course Controller module tests.
Module that contains the tests for the functions in the Course Controller module.
-}
module Controllers.CourseControllerTests
( test_courseController
) where
import Config (runDb)
import Control.Monad (unless)
import Controllers.Course (courseInfo, index, retrieveCourse)
import qualified Data.ByteString.Lazy.Char8 as BL
import qualified Data.Map as Map
import Data.Maybe (fromMaybe)
import qualified Data.Text as T
import Database.Persist.Sqlite (SqlPersistM, insert_)
import Database.Tables (Courses (..))
import Happstack.Server (rsBody, rsCode)
import Test.Tasty (TestTree)
import Test.Tasty.HUnit (assertEqual, testCase)
import TestHelpers (clearDatabase, mockGetRequest, runServerPart, runServerPartWith, withDatabase)
-- | List of test cases as (input course name, course data, status code, expected JSON output)
retrieveCourseTestCases :: [(String, T.Text, Map.Map T.Text T.Text, Int, String)]
retrieveCourseTestCases =
[ ("Course exists",
"STA238",
Map.fromList [
("name", "STA238H1"),
("title", "Probability, Statistics and Data Analysis II"),
("description", "An introduction to statistical inference and practice. Statistical models and parameters, estimators of parameters and their statistical properties, methods of estimation, confidence intervals, hypothesis testing, likelihood function, the linear model. Use of statistical computation for data analysis and simulation."),
("prereqs", "STA237H1/ STA247H1/ STA257H1/ STAB52H3/ STA256H5"),
("exclusions", "ECO220Y1/ ECO227Y1/ GGR270H1/ PSY201H1/ SOC300H1/ SOC202H1/ SOC252H1/ STA220H1/ STA221H1/ STA255H1/ STA248H1/ STA261H1/ STA288H1/ EEB225H1/ STAB22H3/ STAB27H3/ STAB57H3/ STA220H5/ STA221H5/ STA258H5/ STA260H5/ ECO220Y5/ ECO227Y5"),
("breadth", "The Physical and Mathematical Universes (5)"),
("distribution", "null"),
("prereqString", "STA237H1/ STA247H1/ STA257H1/ STAB52H3/ STA256H5"),
("coreqs", "CSC108H1/ CSC110Y1/ CSC148H1 *Note: the corequisite may be completed either concurrently or in advance."),
("videoUrls", "https://example.com/video1, https://example.com/video2")
],
200,
"{\"allMeetingTimes\":[],\"breadth\":null,\"coreqs\":\"CSC108H1/ CSC110Y1/ CSC148H1 *Note: the corequisite may be completed either concurrently or in advance.\",\"description\":\"An introduction to statistical inference and practice. Statistical models and parameters, estimators of parameters and their statistical properties, methods of estimation, confidence intervals, hypothesis testing, likelihood function, the linear model. Use of statistical computation for data analysis and simulation.\",\"distribution\":null,\"exclusions\":\"ECO220Y1/ ECO227Y1/ GGR270H1/ PSY201H1/ SOC300H1/ SOC202H1/ SOC252H1/ STA220H1/ STA221H1/ STA255H1/ STA248H1/ STA261H1/ STA288H1/ EEB225H1/ STAB22H3/ STAB27H3/ STAB57H3/ STA220H5/ STA221H5/ STA258H5/ STA260H5/ ECO220Y5/ ECO227Y5\",\"name\":\"STA238H1\",\"prereqString\":\"STA237H1/ STA247H1/ STA257H1/ STAB52H3/ STA256H5\",\"title\":\"Probability, Statistics and Data Analysis II\",\"videoUrls\":[\"https://example.com/video1\",\"https://example.com/video2\"]}"
),
("Course does not exist",
"STA238",
Map.empty,
404,
"Course not found"
),
("No course provided",
"",
Map.empty,
404,
"Course not found"
)
]
-- | Run a test case (case, input, expected status code, expected output) on the retrieveCourse function.
runRetrieveCourseTest :: String -> T.Text -> Map.Map T.Text T.Text -> Int -> String -> TestTree
runRetrieveCourseTest label courseName courseData expectedCode expectedBody =
testCase label $ do
let currCourseName = fromMaybe "" $ Map.lookup "name" courseData
let videoUrls = case Map.lookup "videoUrls" courseData of
Just urlsText -> map T.strip (T.splitOn "," urlsText)
Nothing -> []
let courseToInsert =
Courses
{ coursesCode = currCourseName
, coursesTitle = Map.lookup "title" courseData
, coursesDescription = Map.lookup "description" courseData
, coursesPrereqs = Map.lookup "prereqs" courseData
, coursesExclusions = Map.lookup "exclusions" courseData
, coursesBreadth = Nothing
, coursesDistribution = Nothing
, coursesPrereqString = Map.lookup "prereqString" courseData
, coursesCoreqs = Map.lookup "coreqs" courseData
, coursesVideoUrls = videoUrls
}
runDb $ do
clearDatabase
unless (T.null currCourseName) $
insert_ courseToInsert
response <- runServerPartWith Controllers.Course.retrieveCourse $ mockGetRequest "/course" [("name", T.unpack courseName)] ""
let statusCode = rsCode response
assertEqual ("Unexpected status code for " ++ label) expectedCode statusCode
let actualBody = BL.unpack $ rsBody response
assertEqual ("Unexpected response body for " ++ label) expectedBody actualBody
-- | Run all the retrieveCourse test cases
runRetrieveCourseTests :: [TestTree]
runRetrieveCourseTests = map (\(label, courseName, courseData, expectedCode, expectedBody) -> runRetrieveCourseTest label courseName courseData expectedCode expectedBody) retrieveCourseTestCases
-- | Helper function to insert courses into the database
insertCourses :: [T.Text] -> SqlPersistM ()
insertCourses = mapM_ insertCourse
where
insertCourse code = insert_ (Courses code Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing [])
-- | List of test cases as (label, input courses, expected output)
indexTestCases :: [(String, [T.Text], String)]
indexTestCases =
[ ("Empty database", [], "")
, ("One course", ["CSC199"], "CSC199\n")
, ("Multiple courses", ["CSC101", "CSC102", "CSC103", "CSC104", "CSC105"],
"CSC101\nCSC102\nCSC103\nCSC104\nCSC105\n")
]
-- | Run a test case (case, input, expected output) on the index function.
runIndexTest :: String -> [T.Text] -> String -> TestTree
runIndexTest label courses expected =
testCase label $ do
runDb $ do
clearDatabase
insertCourses courses
response <- runServerPart Controllers.Course.index
let actual = BL.unpack $ rsBody response
assertEqual ("Unexpected response body for " ++ label) expected actual
-- | Run all the index test cases
runIndexTests :: [TestTree]
runIndexTests = map (\(label, courses, expected) -> runIndexTest label courses expected) indexTestCases
-- | List of test cases as (case, database state, input [dept], expected JSON output) for the courseInfo function
courseInfoTestCases :: [(String, [Courses], T.Text, String)]
courseInfoTestCases =
[ ("Empty Database"
, []
, "STA"
, "[]")
, ("Department with one course in database called"
, [csc108, sta237, sta238]
, "CSC"
, "[{\"allMeetingTimes\":[],\"breadth\":null,\"coreqs\":null,\"description\":\"Programming in a language such as Python. Elementary data types, lists, maps. Program structure: control flow, functions, classes, objects, methods. Algorithms and problem solving. Searching, sorting, and complexity. Unit testing. Floating-point numbers and numerical computation. No prior programming experience required.\",\"distribution\":null,\"exclusions\":\"CSC110Y1, CSC111H1, CSC120H1, CSC121H1, CSC148H1, CSC108H5, CSC148H5, CSCA08H3, CSCA20H3, CSCA48H3\",\"name\":\"CSC108H1\",\"prereqString\":null,\"title\":\"Introduction to Computer Programming\",\"videoUrls\":[]}]")
, ("Department with two courses in database called"
, [csc108, sta237, sta238]
, "STA"
, "[{\"allMeetingTimes\":[],\"breadth\":null,\"coreqs\":\"( CSC108H1/ equivalent programming experience)/ CSC110Y1/ CSC148H1 *Note: the corequisite may be completed either concurrently or in advance.\",\"description\":\"An introduction to probability using simulation and mathematical frameworks, with emphasis on the probability needed for more advanced study in statistical practice. Topics covered include probability spaces, random variables, discrete and continuous probability distributions, probability mass, density, and distribution functions, expectation and variance, independence, conditional probability, the law of large numbers, the central limit theorem, sampling distributions. Computer simulation will be taught and used extensively for calculations and to guide the theoretical development.\",\"distribution\":null,\"exclusions\":\"STA247H1, STA201H1, STA255H1, STA257H1, ECO227Y1, MAT370H1, STAB52H3, STA256H5, ECO227Y5\",\"name\":\"STA237H1\",\"prereqString\":\"( MAT135H1, MAT136H1)/ MAT137Y1/ MAT157Y1/ ( MATA30H3, MATA36H3)/ ( MATA31H3, MATA37H3)/ ( MAT135H5, MAT136H5)/ MAT137Y5/ MAT157Y5/ ( MAT137H5, MAT139H5)/ ( MAT157H5, MAT159H5)\",\"title\":\"Probability, Statistics and Data Analysis I\",\"videoUrls\":[]},{\"allMeetingTimes\":[],\"breadth\":null,\"coreqs\":\"CSC108H1/ CSC110Y1/ CSC148H1 *Note: the corequisite may be completed either concurrently or in advance.\",\"description\":\"An introduction to statistical inference and practice. Statistical models and parameters, estimators of parameters and their statistical properties, methods of estimation, confidence intervals, hypothesis testing, likelihood function, the linear model. Use of statistical computation for data analysis and simulation.\",\"distribution\":null,\"exclusions\":\"ECO220Y1/ ECO227Y1/ GGR270H1/ PSY201H1/ SOC300H1/ SOC202H1/ SOC252H1/ STA220H1/ STA221H1/ STA255H1/ STA248H1/ STA261H1/ STA288H1/ EEB225H1/ STAB22H3/ STAB27H3/ STAB57H3/ STA220H5/ STA221H5/ STA258H5/ STA260H5/ ECO220Y5/ ECO227Y5\",\"name\":\"STA238H1\",\"prereqString\":\"STA237H1/ STA247H1/ STA257H1/ STAB52H3/ STA256H5\",\"title\":\"Probability, Statistics and Data Analysis II\",\"videoUrls\":[\"[https://example.com/video1\",\"https://example.com/video2]\"]}]")
, ("Department with no courses in database called"
, [csc108, sta237, sta238]
, "MAT"
, "[]")
, ("Empty department called in a non-empty database -- should return the entire database"
, [csc108, sta237, sta238]
, ""
, "[{\"allMeetingTimes\":[],\"breadth\":null,\"coreqs\":null,\"description\":\"Programming in a language such as Python. Elementary data types, lists, maps. Program structure: control flow, functions, classes, objects, methods. Algorithms and problem solving. Searching, sorting, and complexity. Unit testing. Floating-point numbers and numerical computation. No prior programming experience required.\",\"distribution\":null,\"exclusions\":\"CSC110Y1, CSC111H1, CSC120H1, CSC121H1, CSC148H1, CSC108H5, CSC148H5, CSCA08H3, CSCA20H3, CSCA48H3\",\"name\":\"CSC108H1\",\"prereqString\":null,\"title\":\"Introduction to Computer Programming\",\"videoUrls\":[]},{\"allMeetingTimes\":[],\"breadth\":null,\"coreqs\":\"( CSC108H1/ equivalent programming experience)/ CSC110Y1/ CSC148H1 *Note: the corequisite may be completed either concurrently or in advance.\",\"description\":\"An introduction to probability using simulation and mathematical frameworks, with emphasis on the probability needed for more advanced study in statistical practice. Topics covered include probability spaces, random variables, discrete and continuous probability distributions, probability mass, density, and distribution functions, expectation and variance, independence, conditional probability, the law of large numbers, the central limit theorem, sampling distributions. Computer simulation will be taught and used extensively for calculations and to guide the theoretical development.\",\"distribution\":null,\"exclusions\":\"STA247H1, STA201H1, STA255H1, STA257H1, ECO227Y1, MAT370H1, STAB52H3, STA256H5, ECO227Y5\",\"name\":\"STA237H1\",\"prereqString\":\"( MAT135H1, MAT136H1)/ MAT137Y1/ MAT157Y1/ ( MATA30H3, MATA36H3)/ ( MATA31H3, MATA37H3)/ ( MAT135H5, MAT136H5)/ MAT137Y5/ MAT157Y5/ ( MAT137H5, MAT139H5)/ ( MAT157H5, MAT159H5)\",\"title\":\"Probability, Statistics and Data Analysis I\",\"videoUrls\":[]},{\"allMeetingTimes\":[],\"breadth\":null,\"coreqs\":\"CSC108H1/ CSC110Y1/ CSC148H1 *Note: the corequisite may be completed either concurrently or in advance.\",\"description\":\"An introduction to statistical inference and practice. Statistical models and parameters, estimators of parameters and their statistical properties, methods of estimation, confidence intervals, hypothesis testing, likelihood function, the linear model. Use of statistical computation for data analysis and simulation.\",\"distribution\":null,\"exclusions\":\"ECO220Y1/ ECO227Y1/ GGR270H1/ PSY201H1/ SOC300H1/ SOC202H1/ SOC252H1/ STA220H1/ STA221H1/ STA255H1/ STA248H1/ STA261H1/ STA288H1/ EEB225H1/ STAB22H3/ STAB27H3/ STAB57H3/ STA220H5/ STA221H5/ STA258H5/ STA260H5/ ECO220Y5/ ECO227Y5\",\"name\":\"STA238H1\",\"prereqString\":\"STA237H1/ STA247H1/ STA257H1/ STAB52H3/ STA256H5\",\"title\":\"Probability, Statistics and Data Analysis II\",\"videoUrls\":[\"[https://example.com/video1\",\"https://example.com/video2]\"]}]")
]
where
sta237 = Courses
{ coursesCode = "STA237H1"
, coursesTitle = Just "Probability, Statistics and Data Analysis I"
, coursesDescription = Just "An introduction to probability using simulation and mathematical frameworks, with emphasis on the probability needed for more advanced study in statistical practice. Topics covered include probability spaces, random variables, discrete and continuous probability distributions, probability mass, density, and distribution functions, expectation and variance, independence, conditional probability, the law of large numbers, the central limit theorem, sampling distributions. Computer simulation will be taught and used extensively for calculations and to guide the theoretical development."
, coursesPrereqs = Just "( MAT135H1, MAT136H1)/ MAT137Y1/ MAT157Y1/ ( MATA30H3, MATA36H3)/ ( MATA31H3, MATA37H3)/ ( MAT135H5, MAT136H5)/ MAT137Y5/ MAT157Y5/ ( MAT137H5, MAT139H5)/ ( MAT157H5, MAT159H5)"
, coursesExclusions = Just "STA247H1, STA201H1, STA255H1, STA257H1, ECO227Y1, MAT370H1, STAB52H3, STA256H5, ECO227Y5"
, coursesBreadth = Nothing
, coursesDistribution = Nothing
, coursesPrereqString = Just "( MAT135H1, MAT136H1)/ MAT137Y1/ MAT157Y1/ ( MATA30H3, MATA36H3)/ ( MATA31H3, MATA37H3)/ ( MAT135H5, MAT136H5)/ MAT137Y5/ MAT157Y5/ ( MAT137H5, MAT139H5)/ ( MAT157H5, MAT159H5)"
, coursesCoreqs = Just "( CSC108H1/ equivalent programming experience)/ CSC110Y1/ CSC148H1 *Note: the corequisite may be completed either concurrently or in advance."
, coursesVideoUrls = []
}
sta238 = Courses
{ coursesCode = "STA238H1"
, coursesTitle = Just "Probability, Statistics and Data Analysis II"
, coursesDescription = Just "An introduction to statistical inference and practice. Statistical models and parameters, estimators of parameters and their statistical properties, methods of estimation, confidence intervals, hypothesis testing, likelihood function, the linear model. Use of statistical computation for data analysis and simulation."
, coursesPrereqs = Just "STA237H1/ STA247H1/ STA257H1/ STAB52H3/ STA256H5"
, coursesExclusions = Just "ECO220Y1/ ECO227Y1/ GGR270H1/ PSY201H1/ SOC300H1/ SOC202H1/ SOC252H1/ STA220H1/ STA221H1/ STA255H1/ STA248H1/ STA261H1/ STA288H1/ EEB225H1/ STAB22H3/ STAB27H3/ STAB57H3/ STA220H5/ STA221H5/ STA258H5/ STA260H5/ ECO220Y5/ ECO227Y5"
, coursesBreadth = Nothing
, coursesDistribution = Nothing
, coursesPrereqString = Just "STA237H1/ STA247H1/ STA257H1/ STAB52H3/ STA256H5"
, coursesCoreqs = Just "CSC108H1/ CSC110Y1/ CSC148H1 *Note: the corequisite may be completed either concurrently or in advance."
, coursesVideoUrls = [T.pack "[https://example.com/video1", T.pack "https://example.com/video2]"]
}
csc108 = Courses
{ coursesCode = "CSC108H1"
, coursesTitle = Just "Introduction to Computer Programming"
, coursesDescription = Just "Programming in a language such as Python. Elementary data types, lists, maps. Program structure: control flow, functions, classes, objects, methods. Algorithms and problem solving. Searching, sorting, and complexity. Unit testing. Floating-point numbers and numerical computation. No prior programming experience required."
, coursesPrereqs = Nothing
, coursesExclusions = Just "CSC110Y1, CSC111H1, CSC120H1, CSC121H1, CSC148H1, CSC108H5, CSC148H5, CSCA08H3, CSCA20H3, CSCA48H3"
, coursesBreadth = Nothing
, coursesDistribution = Nothing
, coursesPrereqString = Nothing
, coursesCoreqs = Nothing
, coursesVideoUrls = []
}
-- | Run a test case (case, database state, input [dept], expected JSON output) on the courseInfo function
runCourseInfoTest :: String -> [Courses] -> T.Text -> String -> TestTree
runCourseInfoTest label state dept expected =
testCase label $ do
runDb $ do
clearDatabase
mapM_ insert_ state
response <- runServerPartWith Controllers.Course.courseInfo $ mockGetRequest "/course-info" [("dept", T.unpack dept)] ""
let actual = BL.unpack $ rsBody response
assertEqual ("Unexpected response body for " ++ label) expected actual
-- | Run all courseInfo test cases
runCourseInfoTests :: [TestTree]
runCourseInfoTests = map (\(label, state, dept, expected) -> runCourseInfoTest label state dept expected) courseInfoTestCases
-- | Test suite for Course Controller Module
test_courseController :: TestTree
test_courseController = withDatabase "Course Controller tests" (runRetrieveCourseTests ++
runIndexTests ++ runCourseInfoTests)