Skip to content

travis: Build all stubs, and test all stubs except for untestable ones #464

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Jan 8, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,27 @@ script:
exercisename=$(basename "$exercise")
pushd ${exercise}

examplename="stub"
Copy link
Member Author

@petertseng petertseng Jan 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these lines (stub-testing code) have very high duplication with the example-testing code below. I'm not sure if it's desirable that we deduplicate that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems fine for me. If we change our mind we can rewrite it later. 👍

buildfolder="${TRAVIS_BUILD_DIR}/build/${exercisename}/${examplename}"
mkdir -p "${buildfolder}"
cp -rL stack.yaml package.yaml src test "${buildfolder}"

pushd $buildfolder

examplecache="${HOME}/.foldercache/${exercisename}/${examplename}/.stack-work"
mkdir -p "$examplecache"
ln -f -s "$examplecache"

if [ -f "${exercise}/.meta/DONT-TEST-STUB" ]; then
echo "only building stub"
stack build ${SET_RESOLVER} --install-ghc --no-terminal
else
echo "testing stub"
stack test ${SET_RESOLVER} --install-ghc --no-terminal --no-run-tests
fi

popd

if ! stat -t examples/*/ > /dev/null 2>&1; then
echo "No examples for ${exercise}!"
exit 1
Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,13 @@ To fix a bug you should [create a pull request from a fork](https://help.github.
You should have [Stack](http://docs.haskellstack.org/) installed in your system to make contributing to this repository easier.

### Stub solution
The stub solution must compile together with the test suite. It should be as general as possible in order to not exclude any possible solutions. It should take Haskell specifics into account (for example use `Maybe` instead of a dummy return value). It should not contain any comments (people might forget to remove them), you can use the hints file instead.
The stub solution should be as general as possible in order to not exclude any possible solutions. It should take Haskell specifics into account (for example use `Maybe` instead of a dummy return value). It should not contain any comments (people might forget to remove them), you can use the hints file instead.

The stub solution must compile by itself (with `stack build`).
Ideally, it would also compile together with the test suite (with `stack test --no-run-tests`).
These two conditions are enforced by Travis.
If the second condition cannot be met for a good reason, place the explanation in `.meta/DONT-TEST-STUB` to circumvent the check.
The first condition is always enforced and cannot be circumvented.

### Example solution
The example solution could be inspiration for other language implementors. It doesn't need to be perfect or very elegant. But it should be efficient enough for the test suite to finish in only a few seconds.
Expand Down
1 change: 1 addition & 0 deletions exercises/allergies/.meta/DONT-TEST-STUB
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
We would have to export all the allergens in the stub; let students figure that out.
5 changes: 3 additions & 2 deletions exercises/allergies/HINTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ with `Eq` and `Show` instances, and implement the following functions:
- `allergies`
- `isAllergicTo`

Your can use the provided signatures if you are unsure about the types, but
don't let them restrict your creativity.
You will find a dummy data declaration and type signatures already in place,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is too different from the original ("Don't let them restrict your creativity"), please help me to combine the two in a sensible manner.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is great the way it is. 👍

but it is up to you to define the functions and create a meaningful data type,
newtype or type synonym.
2 changes: 2 additions & 0 deletions exercises/allergies/src/Allergies.hs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
module Allergies (Allergen(..), allergies, isAllergicTo) where

data Allergen = Dummy

allergies :: Int -> [Allergen]
allergies = undefined

Expand Down
5 changes: 3 additions & 2 deletions exercises/bank-account/HINTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ The amount may be negative for a withdrawal.

The initial balance of the bank account should be 0.

Your can use the provided signatures if you are unsure about the types, but
don't let them restrict your creativity.
You will find a dummy data declaration and type signatures already in place,
but it is up to you to define the functions and create a meaningful data type,
newtype or type synonym.
2 changes: 2 additions & 0 deletions exercises/bank-account/src/BankAccount.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ module BankAccount
, openAccount
) where

data BankAccount = Dummy

closeAccount :: BankAccount -> IO ()
closeAccount = undefined

Expand Down
1 change: 1 addition & 0 deletions exercises/clock/.meta/DONT-TEST-STUB
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
We ask for the Clock to be an instance of Num; let students figure this out.
5 changes: 3 additions & 2 deletions exercises/clock/HINTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ The function `fromInteger`, from `Num`, must convert minutes
to 24 hour clock time. It is not necessary to have a sensible
implementation of `abs` or `signum`.

Your can use the provided signatures if you are unsure about the types, but
don't let them restrict your creativity.
You will find a dummy data declaration and type signatures already in place,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is too different from the original ("Don't let them restrict your creativity"), please help me to combine the two in a sensible manner.

but it is up to you to define the functions and create a meaningful data type,
newtype or type synonym.
2 changes: 2 additions & 0 deletions exercises/clock/src/Clock.hs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
module Clock (clockHour, clockMin, fromHourMin, toString) where

data Clock = Dummy

clockHour :: Clock -> Int
clockHour = undefined

Expand Down
2 changes: 2 additions & 0 deletions exercises/grade-school/.meta/DONT-TEST-STUB
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
No type signatures on functions (TODO: Should we have them?),
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you believe we should have them, I will gladly add them and remove this DONT-TEST-STUB

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see no reason to not have them. 👍
But we can also fix that later.

and this makes it impossible to ensure that the result of `grade` is `Eq`.
4 changes: 4 additions & 0 deletions exercises/grade-school/HINTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@ and implement the following functions:
- `empty`
- `grade`
- `sorted`

You will find a dummy data declaration already in place, but it is up to you to
define the functions and create a meaningful data type, newtype or type
synonym.
2 changes: 2 additions & 0 deletions exercises/grade-school/src/School.hs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
module School (School, add, empty, grade, sorted) where

data School = Dummy

add = undefined

empty = undefined
Expand Down
1 change: 1 addition & 0 deletions exercises/largest-series-product/src/Series.hs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
module Series (largestProduct) where

largestProduct :: Int -> String -> Maybe Integer
largestProduct = undefined
5 changes: 3 additions & 2 deletions exercises/linked-list/HINTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ and implement the following functions:
- `unshift`
- `shift`

You will find the type signatures already in place, but it is up to you
to define the functions.
You will find a dummy data declaration and type signatures already in place,
but it is up to you to define the functions and create a meaningful data type,
newtype or type synonym.
2 changes: 2 additions & 0 deletions exercises/linked-list/src/Deque.hs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
module Deque (Deque, mkDeque, pop, push, shift, unshift) where

data Deque a = Dummy

mkDeque :: IO (Deque a)
mkDeque = undefined

Expand Down
5 changes: 3 additions & 2 deletions exercises/matrix/HINTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ with `Eq` and `Show` instances, and implement the following functions:
- `shape`
- `transpose`

You will find the type signatures already in place, but it is up to you
to define the functions.
You will find a dummy data declaration and type signatures already in place,
but it is up to you to define the functions and create a meaningful data type,
newtype or type synonym.

No validation of input is required. Let it fail if the matrix is not
rectangular, invalid chars are encountered, etc.
Expand Down
2 changes: 2 additions & 0 deletions exercises/matrix/src/Matrix.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ module Matrix

import Data.Vector (Vector)

data Matrix a = Dummy deriving (Eq, Show)

cols :: Matrix a -> Int
cols = undefined

Expand Down
2 changes: 2 additions & 0 deletions exercises/meetup/.meta/DONT-TEST-STUB
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Can't build because the parameters of meetupDay are unused
Would also have to export all the individual days of the week in stub; let students figure that out.
5 changes: 3 additions & 2 deletions exercises/meetup/HINTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
To complete this exercise, you need to create the data types `Weekday`
and `Schedule`, and implement the function `meetupDay`.

You will find the type signature for `meetupDay` already in place,
but it is up to you to define the function.
You will find the type signature for `meetupDay` and dummy data declarations
already in place, but it is up to you to define the function and create
meaningful data types, newtypes or type synonyms.
3 changes: 3 additions & 0 deletions exercises/meetup/src/Meetup.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,8 @@ module Meetup (Weekday(..), Schedule(..), meetupDay) where

import Data.Time.Calendar (Day)

data Schedule = Dummy
data Weekday = Dummy2

meetupDay :: Schedule -> Weekday -> Integer -> Int -> Day
meetupDay schedule weekday year month = undefined
2 changes: 2 additions & 0 deletions exercises/pythagorean-triplet/.meta/DONT-TEST-STUB
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
No function signatures, since we give students the freedom to define mkTriplet how they want
But this means we can't make sure that the result of `mkTriplet` is `Eq`
5 changes: 3 additions & 2 deletions exercises/robot-name/HINTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ as a mutable variable, and implement the following functions:
- `resetName`
- `robotName`

You will find the type signatures already in place, but it is up to you
to define the functions.
You will find a dummy data declaration and type signatures already in place,
but it is up to you to define the functions and create a meaningful data type,
newtype or type synonym.
2 changes: 2 additions & 0 deletions exercises/robot-name/src/Robot.hs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
module Robot (Robot, mkRobot, resetName, robotName) where

data Robot = Dummy

mkRobot :: IO Robot
mkRobot = undefined

Expand Down
5 changes: 3 additions & 2 deletions exercises/robot-simulator/HINTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ and implement the following functions:
- `turnLeft`
- `turnRight`

You will find the type signatures already in place, but it is up to you
to define the functions.
You will find a dummy data declaration and type signatures already in place,
but it is up to you to define the functions and create a meaningful data type,
newtype or type synonym.
2 changes: 2 additions & 0 deletions exercises/robot-simulator/src/Robot.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ data Bearing = North
| West
deriving (Eq, Show)

data Robot = Dummy

bearing :: Robot -> Bearing
bearing = undefined

Expand Down
1 change: 1 addition & 0 deletions exercises/secret-handshake/.meta/DONT-TEST-STUB
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
No signature, so students can figure out accepting strings and ints.
5 changes: 3 additions & 2 deletions exercises/simple-linked-list/HINTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ and implement the following functions:
- `reverseLinkedList`
- `toList`

You will find the type signatures already in place, but it is up to you
to define the functions.
You will find a dummy data declaration and type signatures already in place,
but it is up to you to define the functions and create a meaningful data type,
newtype or type synonym.
2 changes: 2 additions & 0 deletions exercises/simple-linked-list/src/LinkedList.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ module LinkedList
, toList
) where

data LinkedList a = Dummy

datum :: LinkedList a -> a
datum = undefined

Expand Down
1 change: 1 addition & 0 deletions exercises/space-age/.meta/DONT-TEST-STUB
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
We would have to export all the planets in the stub; let students figure that out.
3 changes: 1 addition & 2 deletions exercises/sublist/HINTS.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
## Hints

To complete this exercise, you need to create the data type `Sublist`,
with `Eq` and `Show` instances, and implement the `sublist` function.
To complete this exercise, you need to implement the `sublist` function.
3 changes: 3 additions & 0 deletions exercises/sublist/src/Sublist.hs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
module Sublist (Sublist(..), sublist) where

data Sublist = Equal | Sublist | Superlist | Unequal deriving (Eq, Show)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potentially controversial. If we don't do this though, we have to DONT-TEST-STUB Sublist. I think it's reasonable to do it because it's not the student really has a choice on how to do this, they'll just read the test file and do it this way.

compare to:

  • go-counting where we define data Color = Black | White
  • connect where we define data Mark = Cross | Nought
  • bowling where we define data BowlingError = IncompleteGame | InvalidRoll { rollIndex :: Int, rollValue :: Int }
  • robot-simulator where we define data Bearing = North | East | South | West

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed!

I'm usually in favor of anything to avoid the students having to read the test file.

Haskell is already hard enough to learn, and it is better to allow the students to see a lot of data declarations until they get used to it than let them stuck reading the test suites.


sublist :: [a] -> [a] -> Sublist
sublist = undefined
2 changes: 2 additions & 0 deletions exercises/zipper/src/Zipper.hs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ data BinTree a = BT { btValue :: a
, btRight :: Maybe (BinTree a)
} deriving (Eq, Show)

data Zipper a = Dummy deriving (Eq, Show)

fromTree :: BinTree a -> Zipper a
fromTree = undefined

Expand Down