Solutions
Solution 1: Unit Testing with FunSuite
import org.scalatest.funsuite.AnyFunSuite
class StringUtilityTest extends AnyFunSuite
test("reverse should reverse a string")
assert(StringUtility.reverse("hello") === "olleh")
test("reverse should handle empty string")
assert(StringUtility.reverse("") === "")
test("isPalindrome should return true for a palindrome")
assert(StringUtility.isPalindrome("madam"))
test("isPalindrome should return false for a non-palindrome")
assert(!StringUtility.isPalindrome("hello"))
For the ShoppingCart
exercise, let's first define the solution for the ShoppingCart
class and then proceed with writing a test suite for it using ScalaTest.
Implementing the ShoppingCart and Item
Here's a basic implementation of the ShoppingCart
class and Item
case class:
Writing Tests for the ShoppingCart
Now, let's write tests for this ShoppingCart
implementation. We'll test adding items, removing items, applying discounts, and calculating the total.
import org.scalatest.funsuite.AnyFunSuite
import org.scalatest.matchers.should.Matchers
class ShoppingCartTest extends AnyFunSuite with Matchers
test("Adding items to the shopping cart should increase total accordingly")
val cart = new ShoppingCart
cart.addItem(Item("1", "Apple", 0.60, 1))
cart.addItem(Item("2", "Banana", 0.40, 2))
cart.total shouldEqual 1.40
test("Removing items from the shopping cart should decrease total accordingly")
val cart = new ShoppingCart
cart.addItem(Item("1", "Apple", 0.60, 1))
cart.addItem(Item("2", "Banana", 0.40, 2))
cart.removeItem("2")
cart.total shouldEqual 0.60
test("Applying a discount should reduce the total price")
val cart = new ShoppingCart
cart.addItem(Item("1", "Apple", 1.00, 2)) // Total before discount: 2.00
cart.applyDiscount("DISCOUNT10") // 10% discount
cart.total shouldEqual 1.80 // 10% off of 2.00
test("Adding multiple quantities of an item should be reflected in the total")
val cart = new ShoppingCart
cart.addItem(Item("1", "Apple", 0.50, 2)) // 2 Apples
cart.total shouldEqual 1.00
test("Adding the same item again increases its quantity")
val cart = new ShoppingCart
cart.addItem(Item("1", "Apple", 0.50, 1))
cart.addItem(Item("1", "Apple", 0.50, 1)) // Adding again
cart.total shouldEqual 1.00 // Reflects total for 2 Apples
Solution 3: Testing a Password Validator
Tests for the PasswordValidator
might look like this:
import org.scalatest.funsuite.AnyFunSuite
import org.scalatest.matchers.should.Matchers
class PasswordValidatorTest extends AnyFunSuite with Matchers:
test("A valid password")
assert(PasswordValidator.isValid("ValidPass123"))
test("Password is too short")
PasswordValidator.isValid("Short1") should be(false)
test("Password lacks a digit")
PasswordValidator.isValid("NoDigitsHere!") should be(false)
test("Password lacks an uppercase letter")
PasswordValidator.isValid("alllowercase1") should be(false)
test("Password lacks a lowercase letter")
PasswordValidator.isValid("ALLUPPERCASE1") should be(false)
Solution 4: Property-Based Testing for a String Concatenation Utility
For property-based tests of StringConcatenationUtility
, using ScalaTest with ScalaCheck:
import org.scalatest.funsuite.AnyFunSuite
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
import org.scalatest.matchers.should.Matchers
import org.scalacheck.Prop.forAll
class StringConcatenationUtilityTest extends AnyFunSuite with ScalaCheckPropertyChecks with Matchers:
test("Concatenating two strings should include both with a space in between")
forAll { (a: String, b: String) =>
StringConcatenationUtility.concatenate(a, b) should be (s"$a $b")
test("Concatenating an empty string with a non-empty string results in the latter with an extra space")
forAll { (a: String) =>
StringConcatenationUtility.concatenate("", a) should startWith (" ")
StringConcatenationUtility.concatenate(a, "") should endWith (" ")
Solution 5: Testing a Fibonacci Number Generator
Tests for FibonacciGenerator
could be:
class FibonacciGeneratorTest extends AnyFunSuite with Matchers:
test("Fibonacci numbers for known values")
val knownValues = Seq((0, 0), (1, 1), (2, 1), (3, 2), (4, 3), (5, 5), (6, 8), (7, 13))
knownValues.foreach { case (n, expected) =>
FibonacciGenerator.fibonacci(n) should be(expected)
test("Fibonacci number for negative input")
intercept[IllegalArgumentException] {
FibonacciGenerator.fibonacci(-1)
Note: The performance or stack overflow test is not included as it's more about optimization and implementation strategy rather than simple functional testing.
Solution 6: Integration Testing for a File Processing Utility
An integration test for FileProcessingUtility
involves file operations:
import org.scalatest.funsuite.AnyFunSuite
import org.scalatest.BeforeAndAfter
import java.nio.file.{Files, Paths}
class FileProcessingUtilityTest extends AnyFunSuite with BeforeAndAfter with Matchers:
val inputPath = "testInput.txt"
val outputPath = "testOutput.txt"
before {
val content = "This is a test."
Files.write(Paths.get(inputPath), content.getBytes)
}
after {
Files.deleteIfExists(Paths.get(inputPath))
Files.deleteIfExists(Paths.get(outputPath))
}
test("File processing converts text to uppercase")
FileProcessingUtility.processFile(inputPath, outputPath)
val result = Files.readAllLines(Paths.get(outputPath)).get(0)
result should be("THIS IS A TEST.")
test("Handling of non-existent input files")
intercept[Exception] {
FileProcessingUtility.processFile("nonExistentFile.txt", outputPath)