Skip to content

Repository files navigation

Exploding Kittens

Gradle Build

A complete Java implementation of the card game Exploding Kittens, built as a software-quality engineering exercise: 73 test classes against 63 source classes, with mutation testing, static analysis, and style enforcement all gated by CI.

The game itself is the easy part. The point of this project was to find out what it takes for a test suite to actually be trustworthy — not just green.


Why the tests are the interesting part

A passing test suite proves very little. A test that asserts the wrong thing passes just as happily as one that asserts the right thing. So this project layers four independent checks, each of which catches something the others miss:

LayerToolWhat it catches
Unit testsJUnit 5, Mockito, EasyMockBroken logic in a single class
Acceptance testsCucumber (Gherkin)A rule of the game implemented correctly but wired up wrong
CoverageJaCoCoCode that no test ever executes
Mutation testingPITCode that is executed but never actually asserted on

That last row is the one that changes how you write tests. PIT deliberately injects faults into the compiled bytecode — flipping a conditional, changing + to -, replacing a return value — and then reruns the suite. If the tests still pass, the mutant "survived", and that line of code is not really tested even though coverage reports it as covered.

Configured mutation operators:

mutators.set(listOf(
"CONDITIONALS_BOUNDARY", // < becomes <="INCREMENTS", // ++ becomes --"INVERT_NEGS", // -x becomes x"MATH", // + becomes -"NEGATE_CONDITIONALS", // == becomes !="PRIMITIVE_RETURNS", // return x becomes return 0"VOID_METHOD_CALLS"// a call is removed entirely
))

Writing tests that kill these mutants is a different discipline from writing tests that reach a coverage number. CONDITIONALS_BOUNDARY in particular forces you to test the exact edges — a deck with one card left, a turn counter at its limit — rather than only the comfortable middle of each range.


Architecture

Model–view–controller, with each layer independently testable:

src/main/java/explodingkittens/
├── model/ 31 classes cards, deck, players, turn state
├── exceptions/ 10 classes one type per rule violation
├── controller/ 9 classes game loop, setup, per-card effects
├── view/ 6 classes console rendering and input
├── service/ 4 classes deck construction, shuffling, dealing
└── util/ 2 classes

Two decisions that made the suite possible:

  • Input handling is an interface, not a call to Scanner. Every card that needs a player decision (Favor, Cat Card steal, Defuse placement) takes an input handler, so the controller can be driven by a mock in tests and by the console at runtime.
  • One exception type per rule violation (EmptyDeckException, EmptyPlayersListException, and eight more) rather than a generic IllegalStateException. Tests assert on the specific type, so a test cannot accidentally pass because some other error happened to be thrown.

Running it

Requires JDK 11.

./gradlew build # compile, test, checkstyle, spotbugs
./gradlew run # play in the console
./gradlew test# unit tests only
./gradlew cucumber # acceptance tests (Gherkin features)
./gradlew pitest # mutation testing — the slow, honest one
./gradlew jacocoTestReport

CI (GitHub Actions, JDK 11 Temurin, Gradle 8.10) runs ./gradlew build on every push and pull request to main, so style violations and SpotBugs findings fail the build rather than accumulating.


Game rules implemented

CardEffect
Exploding KittenDrawing it removes you from the game unless you play a Defuse
DefuseCancels an Exploding Kitten; you choose where to bury it back in the deck
AttackThe next player takes two turns in a row
SkipEnd your turn without drawing
FavorA player of your choice gives you one card of their choosing
ShuffleShuffle the draw pile
See the FuturePrivately view the top 2 cards, without rearranging
Draw From the BottomDraw from the bottom of the deck instead of the top
ReverseReverse play order; acts as a Skip in a 2-player game
Time RewindSwap the top 3 cards of the deck with the bottom 3
Switch Deck by HalfSwap the top and bottom halves of the draw pile
Cat CardsTwo matching cats let you steal a random card from another player

Team

Course project for Software Quality Engineering (Northwestern University).

Qimeng Chao · Liming Luo · Shao Jin · Minjun Liang · Xiaoqin Bai


Tech stack

Java 11 · Gradle (Kotlin DSL) · JUnit 5 · Mockito · EasyMock · Cucumber · JaCoCo · PIT mutation testing · Checkstyle · SpotBugs · GitHub Actions

About

Java implementation of the card game, built as a software-quality exercise: 73 test classes to 63 source classes, with mutation testing (PIT), Cucumber acceptance tests, and CI-gated static analysis.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages