Object Oriented Programming | Week 10: Unit Testing

PBO-A 2025 



    Pada pertemuan kali ini, kami mempelajari cara melakukan testing dan debugging dalam proses pembuatan sebuah class. Fokus utama dari tugas ini adalah membuat unit testing untuk menguji fungsionalitas dari class SalesItem. Pengujian tersebut dilakukan melalui class SalesItemTest, yang dirancang berdasarkan class diagram yang telah disediakan untuk memastikan setiap metode pada class SalesItem bekerja sesuai dengan yang diharapkan.

Class SalesItem:
// Source code is decompiled from a .class file using FernFlower decompiler (from Intellij IDEA).
import java.util.ArrayList;
import java.util.Iterator;

public class SalesItem {
   private String name;
   private int price;
   private ArrayList<Comment> comments;

   public SalesItem(String name, int price) {
      this.name = name;
      this.price = price;
      this.comments = new ArrayList();
   }

   public String getName() {
      return this.name;
   }

   public int getPrice() {
      return this.price;
   }

   public int getNumberOfComments() {
      return this.comments.size();
   }

   public boolean addComment(String author, String text, int rating) {
      if (this.ratingInvalid(rating)) {
         return false;
      } else if (this.findCommentByAuthor(author) != null) {
         return false;
      } else {
         this.comments.add(new Comment(author, text, rating));
         return true;
      }
   }

   public void removeComment(int index) {
      if (index >= 0 && index < this.comments.size()) {
         this.comments.remove(index);
      }

   }

   public void upvoteComment(int index) {
      if (index >= 0 && index < this.comments.size()) {
         ((Comment)this.comments.get(index)).upvote();
      }

   }

   public void downvoteComment(int index) {
      if (index >= 0 && index < this.comments.size()) {
         ((Comment)this.comments.get(index)).downvote();
      }

   }

   public void showInfo() {
      System.out.println("*** " + this.name + " ***");
      System.out.println("Price: " + this.priceString(this.price));
      System.out.println();
      System.out.println("Customer comments:");
      Iterator var1 = this.comments.iterator();

      while(var1.hasNext()) {
         Comment comment = (Comment)var1.next();
         System.out.println("-----------------------------------");
         comment.print();
      }

      System.out.println();
      System.out.println("=====================================");
   }

   private boolean ratingInvalid(int rating) {
      return rating < 0 || rating > 5;
   }

   public Comment findMostHelpfulComment() {
      if (this.comments.isEmpty()) {
         return null;
      } else {
         Comment best = (Comment)this.comments.get(0);
         Iterator var2 = this.comments.iterator();

         while(var2.hasNext()) {
            Comment current = (Comment)var2.next();
            if (current.getVoteBalance() > best.getVoteBalance()) {
               best = current;
            }
         }

         return best;
      }
   }

   public Comment findCommentByAuthor(String author) {
      Iterator var2 = this.comments.iterator();

      Comment comment;
      do {
         if (!var2.hasNext()) {
            return null;
         }

         comment = (Comment)var2.next();
      } while(!comment.getAuthor().equals(author));

      return comment;
   }

   private String priceString(int price) {
      int dollars = price / 100;
      int cents = price - dollars * 100;
      return cents <= 9 ? "$" + dollars + ".0" + cents : "$" + dollars + "." + cents;
   }
}


Class Comment:

/**
 * Write a description of class SalesItem here.
 *
 * @author Muhammad Zaky Zein
 * @version 2025.11.01
 */

public class Comment
{
    private String author;
    private String text;
    private int rating;
    private int upvotes;
    private int downvotes;
    
    public Comment(String author, String text, int rating) {
        this.author = author;
        this.text = text;
        this.rating = rating;
        upvotes = 0;
        downvotes = 0;
    }

    public String getAuthor() {
        return author;
    }
    
    public void upvote() {
        upvotes++;
    }

    public void downvote() {
        downvotes++;
    }

    public int getVoteBalance() {
        return upvotes - downvotes;
    }

    public void print() {
        System.out.println("Author: " + author);
        System.out.println("Rating: " + rating);
        System.out.println("Comment: " + text);
        System.out.println("Votes: " + getVoteBalance());
    }
}


Class SalesItemTest:

/**
 * Write a description of class SalesItemTest here.
 *
 * @author Muhammad Zaky Zein
 * @version 2025.11.01
 */

import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class SalesItemTest{
    private SalesItem item;

    @BeforeEach
    void setup() {
        item = new SalesItem("RTX 9090", 9955);
    }

    @Test
    void testNameAndPrice() {
        assertEquals("RTX 9090", item.getName());
        assertEquals(9955, item.getPrice());
    }

    @Test
    void testCommentAddValid() {
        boolean added = item.addComment("John Doe", "Good!", 4);
        assertTrue(added);
        assertEquals(1, item.getNumberOfComments());
    }

    @Test
    void testCommentAddDuplicateAuthor() {
        item.addComment("John Doe", "Fake GPU", 0);
        boolean addedAgain = item.addComment("John Doe", "Very good price to value.", 5);
        assertFalse(addedAgain);
        assertEquals(1, item.getNumberOfComments());
    }

    @Test
    void testCommentAddInvalidRating() {
        boolean added = item.addComment("TungTungSahur", "i'll rate it 10", 10);
        assertFalse(added);
        assertEquals(0, item.getNumberOfComments());
    }

    @Test
    void testCommentRemoveValid() {
        item.addComment("TungTungSahur", "Please don't redeem it!", 2);
        item.removeComment(0);
        assertEquals(0, item.getNumberOfComments());
    }

    @Test
    void testCommentRemoveInvalidIndex() {
        item.addComment("Lonely man", "idk man.. i kinda missed her.", 4);
        item.removeComment(5);
        assertEquals(1, item.getNumberOfComments());
    }

    @Test
    void testCommentUpDownVote() {
        item.addComment("TungTungSahur", "Good product!", 4);
        item.upvoteComment(0);
        item.upvoteComment(0);
        item.downvoteComment(0);
        Comment comment = item.findCommentByAuthor("TungTungSahur");
        assertEquals(1, comment.getVoteBalance()); 
    }

    @Test
    void testCommentFindMostHelpful() {
        item.addComment("TungTungSahur", "TUNG TUNG TUNG!", 4);
        item.addComment("John Doe", "Awesome Graphics card!", 5);
        item.upvoteComment(1); 
        assertEquals("John Doe", item.findMostHelpfulComment().getAuthor());
    }

    @Test
    void testCommentFindByAuthor() {
        item.addComment("Lonely man", ":)", 4);
        Comment comment = item.findCommentByAuthor("Lonely man");
        assertNotNull(comment);
        assertEquals("Lonely man", comment.getAuthor());
        assertNull(item.findCommentByAuthor("TungTungSahur"));
    }
}

  • setup(), Digunakan untuk menyiapkan objek SalesItem baru sebelum setiap pengujian dijalankan. Tujuannya agar setiap test dimulai dengan kondisi awal yang sama.
  • testNameAndPrice(), Menguji apakah metode getName() dan getPrice() mengembalikan nilai yang sesuai dengan data yang diberikan saat objek SalesItem dibuat.
  • testCommentAddValid(), Memastikan bahwa komentar dengan data valid (penulis unik dan rating dalam rentang 1-5) dapat ditambahkan dengan benar, serta jumlah komentar bertambah satu.
  • testCommentAddDuplicateAuthor(), Menguji agar sistem menolak komentar dari penulis yang sama lebih dari sekali. Komentar duplikat tidak boleh ditambahkan, dan jumlah komentar tetap.
  • testCommentAddInvalidRating(), Memverifikasi bahwa komentar dengan nilai rating yang tidak valid (di luar 1-5) tidak diterima dan tidak menambah jumlah komentar.
  • testCommentRemoveValid(), Menguji penghapusan komentar berdasarkan indeks yang valid. Setelah komentar dihapus, jumlah komentar seharusnya berkurang.
  • testCommentRemoveInvalidIndex(), Memastikan bahwa penghapusan dengan indeks yang tidak valid tidak mempengaruhi data komentar yang ada.
  • testCommentUpDownVote(), Menguji sistem pemberian suara (upvote dan downvote) pada komentar. Setelah beberapa kali upvote dan satu kali downvote, nilai keseimbangan suara (vote balance) seharusnya benar.
  • testCommentFindMostHelpful(), Menguji metode pencarian komentar paling membantu, yaitu komentar dengan jumlah upvote tertinggi.
  • testCommentFindByAuthor(), Memastikan metode pencarian komentar berdasarkan nama penulis bekerja dengan benar, mengembalikan objek komentar jika ditemukan, dan null jika tidak ada.




Muhammad Zaky Zein
5025241148







Comments