test: add unit tests for Ranks and Suits to increase coverage

This commit is contained in:
2025-04-07 23:55:03 -04:00
parent efd528d93e
commit c16180bf36
16 changed files with 498 additions and 10 deletions

View File

@@ -4,5 +4,6 @@ ThisBuild / scalaVersion := "3.3.3"
lazy val root = (project in file("."))
.settings(
name := "template-2025-1"
name := "template-2025-1",
libraryDependencies += "org.scalameta" %% "munit" % "0.7.29" % Test
)

View File

@@ -1,10 +1,18 @@
package cards
/**
* Represents a playing card, which has a rank and a suit.
*
* @param rank
* @param suit
* @param rank the rank of the card (e.g., Ace, King, Two)
* @param suit the suit of the card (e.g., Hearts, Spades)
*/
class Cards(val rank: Rank, val suit: Suit) {
class Card(val rank: Rank, val suit: Suit) {
/**
* Returns a string representation of the card.
*
* @return a string combining the rank and suit
*/
override def toString: String = s"$rank of $suit"
}

View File

@@ -1,3 +1,31 @@
package cards
trait Rank
/**
* Represents a playing card rank. Each rank has:
* - an order (1 for Ace, up to 13 for King)
* - a value (can match the order or vary)
* - a rankType (Odd, Even, or Figure)
*/
trait Rank {
/**
* The numerical order of this rank (1 = Ace, 13 = King).
*
* @return an integer that identifies the rank in ascending order
*/
def order: Int
/**
* The numeric value of this rank (could match order or be different).
*
* @return an integer representing the value of this rank
*/
def value: Int
/**
* A string indicating the rank type: "Odd", "Even", or "Figure".
*
* @return a string with the rank type
*/
def rankType: String
}

View File

@@ -0,0 +1,136 @@
package cards
/**
* Represents the Ace rank.
*/
object Ace extends Rank {
/**
* The order of Ace in a standard deck (1).
*
* @return 1
*/
val order: Int = 1
/**
* The value of the Ace rank.
*
* @return 1
*/
val value: Int = 1
/**
* The type of the rank.
*
* @return "Odd"
*/
val rankType: String = "Odd"
}
/**
* Represents the Two rank.
*/
object Two extends Rank {
val order: Int = 2
val value: Int = 2
val rankType: String = "Even"
}
/**
* Represents the Three rank.
*/
object Three extends Rank {
val order: Int = 3
val value: Int = 3
val rankType: String = "Odd"
}
/**
* Represents the Four rank.
*/
object Four extends Rank {
val order: Int = 4
val value: Int = 4
val rankType: String = "Even"
}
/**
* Represents the Five rank.
*/
object Five extends Rank {
val order: Int = 5
val value: Int = 5
val rankType: String = "Odd"
}
/**
* Represents the Six rank.
*/
object Six extends Rank {
val order: Int = 6
val value: Int = 6
val rankType: String = "Even"
}
/**
* Represents the Seven rank.
*/
object Seven extends Rank {
val order: Int = 7
val value: Int = 7
val rankType: String = "Odd"
}
/**
* Represents the Eight rank.
*/
object Eight extends Rank {
val order: Int = 8
val value: Int = 8
val rankType: String = "Even"
}
/**
* Represents the Nine rank.
*/
object Nine extends Rank {
val order: Int = 9
val value: Int = 9
val rankType: String = "Odd"
}
/**
* Represents the Ten rank.
*/
object Ten extends Rank {
val order: Int = 10
val value: Int = 10
val rankType: String = "Even"
}
/**
* Represents the Jack rank.
*/
object Jack extends Rank {
val order: Int = 11
val value: Int = 11
val rankType: String = "Figure"
}
/**
* Represents the Queen rank.
*/
object Queen extends Rank {
val order: Int = 12
val value: Int = 12
val rankType: String = "Figure"
}
/**
* Represents the King rank.
*/
object King extends Rank {
val order: Int = 13
val value: Int = 13
val rankType: String = "Figure"
}

View File

@@ -1,3 +1,15 @@
package cards
trait Suit
/**
* Represents the suit of a playing card.
* Valid suits are: Hearts, Spades, Diamonds, Clubs.
*/
trait Suit {
/**
* Returns the name of the suit as a string.
*
* @return the suit name (e.g., "Hearts", "Clubs")
*/
def name: String
}

View File

@@ -0,0 +1,53 @@
package cards
/**
* Represents the Hearts suit.
*/
object Hearts extends Suit {
/**
* The name of this suit.
*
* @return "Hearts"
*/
val name: String = "Hearts"
}
/**
* Represents the Spades suit.
*/
object Spades extends Suit {
/**
* The name of this suit.
*
* @return "Spades"
*/
val name: String = "Spades"
}
/**
* Represents the Diamonds suit.
*/
object Diamonds extends Suit {
/**
* The name of this suit.
*
* @return "Diamonds"
*/
val name: String = "Diamonds"
}
/**
* Represents the Clubs suit.
*/
object Clubs extends Suit {
/**
* The name of this suit.
*
* @return "Clubs"
*/
val name: String = "Clubs"
}

View File

@@ -1,3 +1,66 @@
package hand
class Hand
import cards.Card
import jokers.Joker
import scala.collection.mutable.ListBuffer
/**
* Represents a Hand that contains a set of Cards and a set of Jokers.
* Does not include any extra logic or scoring yet.
*/
class Hand {
// Mutable collections to store cards and jokers internally
private val cards = ListBuffer[Card]()
private val jokers = ListBuffer[Joker]()
/**
* Adds a Card to the hand.
*
* @param card the card to add
*/
def addCard(card: Card): Unit = cards += card
/**
* Removes a Card from the hand.
*
* @param card the card to remove
*/
def removeCard(card: Card): Unit = cards -= card
/**
* Adds a Joker to the hand.
*
* @param joker the Joker to add
*/
def addJoker(joker: Joker): Unit = jokers += joker
/**
* Removes a Joker from the hand.
*
* @param joker the Joker to remove
*/
def removeJoker(joker: Joker): Unit = jokers -= joker
/**
* Provides an immutable list of cards currently in the hand.
*
* @return a list of cards contained in the hand
*/
def getCards: List[Card] = cards.toList
/**
* Provides an immutable list of jokers currently in the hand.
*
* @return a list of jokers contained in the hand
*/
def getJokers: List[Joker] = jokers.toList
/**
* Returns a string representation of the hand, listing cards and jokers.
*
* @return a string of cards and jokers
*/
override def toString: String =
s"Hand(cards: $cards, jokers: $jokers)"
}

View File

@@ -1,3 +1,22 @@
package jokers
class Joker
/**
* Represents a Joker card with a specific type.
*
* Allowed types are:
* - "Greedy Joker"
* - "Devious Joker"
* - "Even Steven"
* - "Scary Face"
*
* @param jokerType the type of this Joker as a String
*/
class Joker(val jokerType: String) {
/**
* Returns a string representation of the Joker.
*
* @return the joker type
*/
override def toString: String = jokerType
}

View File

@@ -1,3 +1,18 @@
package score
class score
/**
* Represents a player's score in the game.
*
* @param chips the number of chips a player has
* @param multiplier a factor that multiplies the chips
*/
class Score(var chips:Int, var multiplier: Int) {
/**
* Calculates the total score based on the chips and multiplier.
*
* @return the result of chips * multiplier
*/
def total:Int =chips *multiplier
}

View File

@@ -0,0 +1,21 @@
package cards
import munit.FunSuite
class CardTest extends FunSuite {
test("Card should store rank and suit correctly") {
val card = new Card(Ace, Hearts)
assertEquals(card.rank, Ace)
assertEquals(card.suit, Hearts)
}
test("Card toString should return readable string") {
val card = new Card(King, Spades)
val result = card.toString
assert(result.contains("King"))
assert(result.contains("Spades"))
}
}

View File

@@ -0,0 +1,32 @@
package cards
import munit.FunSuite
class RankTest extends FunSuite {
test("All ranks should have correct rankType, order and value") {
val ranks = Seq(Ace, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King)
val expected = Seq(
("Ace", 1, "Odd"),
("Two", 2, "Even"),
("Three", 3, "Odd"),
("Four", 4, "Even"),
("Five", 5, "Odd"),
("Six", 6, "Even"),
("Seven", 7, "Odd"),
("Eight", 8, "Even"),
("Nine", 9, "Odd"),
("Ten", 10, "Even"),
("Jack", 11, "Figure"),
("Queen", 12, "Figure"),
("King", 13, "Figure")
)
for ((rank, (name, order, rankType)) <- ranks.zip(expected)) {
assertEquals(rank.order, order, s"$name order mismatch")
assertEquals(rank.value, order, s"$name value mismatch")
assertEquals(rank.rankType, rankType, s"$name rankType mismatch")
}
}
}

View File

@@ -0,0 +1,15 @@
package cards
import munit.FunSuite
class SuitTest extends FunSuite {
test("All suits should return correct name") {
val suits = Seq(Hearts, Spades, Clubs, Diamonds)
val expected = Seq("Hearts", "Spades", "Clubs", "Diamonds")
for ((suit, name) <- suits.zip(expected)) {
assertEquals(suit.name, name)
}
}
}

View File

@@ -0,0 +1,46 @@
package hand
import munit.FunSuite
import cards.{Card, Ace, Hearts}
import jokers.Joker
class HandTest extends FunSuite {
test("addCard should add a card to the hand") {
val hand = new Hand
val card = new Card(Ace, Hearts)
hand.addCard(card)
assert(hand.getCards.contains(card))
}
test("removeCard should remove a card from the hand") {
val hand = new Hand
val card = new Card(Ace, Hearts)
hand.addCard(card)
hand.removeCard(card)
assert(!hand.getCards.contains(card))
}
test("addJoker should add a joker to the hand") {
val hand = new Hand
val joker = new Joker("Greedy Joker")
hand.addJoker(joker)
assert(hand.getJokers.contains(joker))
}
test("removeJoker should remove a joker from the hand") {
val hand = new Hand
val joker = new Joker("Greedy Joker")
hand.addJoker(joker)
hand.removeJoker(joker)
assert(!hand.getJokers.contains(joker))
}
}

View File

@@ -0,0 +1,17 @@
package jokers
import munit.FunSuite
class JokerTest extends FunSuite {
test("Joker should store its type correctly") {
val joker = new Joker("Greedy Joker")
assertEquals(joker.jokerType, "Greedy Joker")
}
test("Joker toString should return the joker type") {
val joker = new Joker("Scary Face")
assertEquals(joker.toString, "Scary Face")
}
}

View File

@@ -1 +0,0 @@
package model

View File

@@ -0,0 +1,23 @@
package score
import munit.FunSuite
class ScoreTest extends FunSuite {
test("total should return chips multiplied by multiplier") {
val score = new Score(10, 2)
assertEquals(score.total, 20)
}
test("chips can be updated") {
val score = new Score(5, 2)
score.chips = 7
assertEquals(score.total, 14)
}
test("multiplier can be updated") {
val score = new Score(5, 2)
score.multiplier = 3
assertEquals(score.total, 15)
}
}