diff --git a/src/opinion/SocialNetwork.java b/src/opinion/SocialNetwork.java index 7a1c9b6bd1a51bc9dec9879276100450e68a945b..7a5ba3fce88bd6c3c704944a38e57b1f5e2895fb 100644 --- a/src/opinion/SocialNetwork.java +++ b/src/opinion/SocialNetwork.java @@ -1,13 +1,8 @@ package opinion; -import java.util.LinkedList; +import exceptions.*; -import exceptions.BadEntryException; -import exceptions.ItemBookAlreadyExistsException; -import exceptions.ItemFilmAlreadyExistsException; -import exceptions.MemberAlreadyExistsException; -import exceptions.NotItemException; -import exceptions.NotMemberException; +import java.util.LinkedList; /** * Skeleton for the SocialNetwork @@ -43,7 +38,6 @@ public class SocialNetwork implements ISocialNetwork { */ @Override public int nbMembers() { - // TODO Auto-generated method stub return nbmembers; } @@ -65,8 +59,7 @@ public class SocialNetwork implements ISocialNetwork { */ @Override public int nbBooks() { - // TODO Auto-generated method stub - return listBook.size(); + return nbbooks; } /** @@ -87,18 +80,18 @@ public class SocialNetwork implements ISocialNetwork { /** * Validates the format of a user's login and password (not empty or too short) * - * @param login the login to be validated + * @param login the login to be validated * @param password the password to be validated * @return true if login and password are valid * @throws BadEntryException if either login or password is invalid */ - public boolean validateuser(String login, String password) throws BadEntryException { + public boolean validateUser(String login, String password) throws BadEntryException { boolean result = false; - if (login == null || login.length() <= 1) { - throw new BadEntryException("login is null or empty"); + if (login == null || login.length() <= 1) { + throw new BadEntryException("Error: Login is null or empty"); } if (password == null || password.length() < 4) { - throw new BadEntryException("password is null or empty"); + throw new BadEntryException("Error: Password is null or empty"); } return true; } @@ -106,7 +99,7 @@ public class SocialNetwork implements ISocialNetwork { /** * Authenticates a user's login and password * - * @param login the login of the user + * @param login the login of the user * @param password the password of the user * @return true if password corresponds to registered login, false if wrong password */ @@ -127,10 +120,9 @@ public class SocialNetwork implements ISocialNetwork { * @return true if book does not exist yet in system, false if already exists * @throws BadEntryException if title is empty or too short */ - public boolean validatebook(String title) throws BadEntryException { - boolean result = false; - if (title == null || title.length() <= 1) { - throw new BadEntryException("title is null or empty"); + public boolean validateBook(String title) throws BadEntryException { + if (title == null || title.trim().length() <= 1) { + throw new BadEntryException("Error: Title is null or too short"); } for (Book b : listBook) { if (b.compareTitle(title)) { @@ -143,18 +135,18 @@ public class SocialNetwork implements ISocialNetwork { /** * Adds a new member to the social network. * - * @param login the new member's login + * @param login the new member's login * @param password the new member's password - * @param profile a free String describing the new member's profile - * @throws BadEntryException if parameter is null or too short + * @param profile a free String describing the new member's profile + * @throws BadEntryException if parameter is null or too short * @throws MemberAlreadyExistsException if login already exists */ @Override public void addMember(String login, String password, String profile) throws BadEntryException, MemberAlreadyExistsException { if (profile == null) { - throw new BadEntryException("profile is null or empty"); + throw new BadEntryException("Error: Profile is null or empty"); } - validateuser(login, password); + validateUser(login, password); if (memberRegister(login)) { throw new MemberAlreadyExistsException(); } @@ -163,32 +155,37 @@ public class SocialNetwork implements ISocialNetwork { nbmembers++; } + @Override + public void addItemFilm(String login, String password, String title, String kind, String director, String scriptwriter, int duration) + throws BadEntryException, NotMemberException, ItemFilmAlreadyExistsException { + } + /** * Adds a new book to the social network. * - * @param login login of the member adding the book + * @param login login of the member adding the book * @param password password of the member adding the book - * @param title the new book's title - * @param kind the new book's kind - * @param author the new book's author - * @param nbPages number of pages of the new book's - * @throws BadEntryException if any input is invalid (empty or number pages equal or less than 0) - * @throws NotMemberException if login or password is wrong + * @param title the new book's title + * @param kind the new book's kind + * @param author the new book's author + * @param nbPages number of pages of the new book's + * @throws BadEntryException if any input is invalid (empty or number pages equal or less than 0) + * @throws NotMemberException if login or password is wrong * @throws ItemBookAlreadyExistsException if book already exists in system */ @Override public void addItemBook(String login, String password, String title, String kind, String author, int nbPages) throws BadEntryException, NotMemberException, ItemBookAlreadyExistsException { - validateuser(login, password); + validateUser(login, password); if (title == null || title.trim().isEmpty()) - throw new BadEntryException("Error: Invalid title."); + throw new BadEntryException("Error: Title is null or empty"); if (kind == null || kind.trim().isEmpty()) - throw new BadEntryException("Error: Invalid kind."); + throw new BadEntryException("Error: Kind is null or empty"); if (author == null || author.trim().isEmpty()) - throw new BadEntryException("Error: Invalid author."); + throw new BadEntryException("Error: Author is null or empty"); if (nbPages <= 0) - throw new BadEntryException("Error: Invalid number of pages."); + throw new BadEntryException("Error: Page number is null or less"); if (!authenticateUser(login, password)) - throw new NotMemberException("Error: User doesn't exist"); + throw new NotMemberException("Error: Invalid login or password"); for (Book b : listBook) { if (b.compareTitle(title)) { throw new ItemBookAlreadyExistsException(); @@ -200,64 +197,41 @@ public class SocialNetwork implements ISocialNetwork { } @Override - public void addItemFilm(String login, String password, String title, String kind, String director, String scriptwriter, int duration) - throws BadEntryException, NotMemberException, ItemFilmAlreadyExistsException { - } - - @Override - public float reviewItemFilm(String login, String password, String title, - float mark, String comment) throws BadEntryException, NotMemberException, NotItemException { + public float reviewItemFilm(String login, String password, String title, float mark, String comment) + throws BadEntryException, NotMemberException, NotItemException { // TODO Auto-generated method stub return 0; } /** - * Displays a whole list of registered members * - * @return list of registered members + * @param login login of the member adding the review + * @param password password of the member adding the review + * @param title the reviewed book's title + * @param mark the mark given by the member for this book + * @param comment the comment given by the member for this book + * @return average mark of current book + * @throws BadEntryException if any input is invalid (mark is out of range) + * @throws NotMemberException if login or password is wrong + * @throws NotItemException if book doesn't exist */ - public String toString() { - if (listMember.isEmpty()) { - return "There are currently no registered members :("; - } - String ret = "\nRegistered members:\n"; - int counter = 1; - for (Member m : listMember) { - ret += counter + ". " + m.toString() + "\n"; - counter++; - } - return ret.trim(); - } - - @Override - public float reviewItemBook(String login, String password, String title, - float mark, String comment) throws BadEntryException, - NotMemberException, NotItemException { - - // Validate user - validateuser(login, password); - + public float reviewItemBook(String login, String password, String title, float mark, String comment) + throws BadEntryException, NotMemberException, NotItemException { + validateUser(login, password); if (comment == null) { - throw new BadEntryException("Comment cannot be null."); + throw new BadEntryException("Error: Comment is null"); } - if (mark < 0.0f || mark > 5.0f) { - throw new BadEntryException("Mark must be between 0.0 and 5.0."); + throw new BadEntryException("Error: Mark must be between 0.0 and 5.0"); } - - // Verify existence of book - boolean bookExists = validatebook(title); + boolean bookExists = validateBook(title); if (!bookExists) { - throw new NotItemException("Book not found."); + throw new NotItemException("Error: Book not found"); } - - // Member authentication if (!authenticateUser(login, password)) { - throw new NotMemberException("Invalid login or password."); + throw new NotMemberException("Error: Invalid login or password"); } - - // Search book Book targetBook = null; for (Book b : listBook) { if (b.compareTitle(title)) { @@ -265,37 +239,52 @@ public class SocialNetwork implements ISocialNetwork { break; } } - if (targetBook == null) { - throw new NotItemException("Book not found."); + throw new NotItemException("Error: Book not found"); } - - // Add or replace a review targetBook.addOrUpdateReview(login.trim(), mark, comment); - - // Returns the new average mark return targetBook.getAverageMark(); } - + /** + * + * @param title title of searched item(s) + * @return the search result of book or film added + * @throws BadEntryException if any input is invalid (title is empty or too short) + */ @Override public LinkedList<String> consultItems(String title) throws BadEntryException { if (title == null || title.trim().length() <= 1) { - throw new BadEntryException("Title is null or too short."); + throw new BadEntryException("Error: Title is null or too short"); } - String formattedTitle = title.trim().toLowerCase(); LinkedList<String> result = new LinkedList<>(); - for (Book b : listBook) { if (b.getTitle().toLowerCase().contains(formattedTitle)) { result.add(b.toString()); } } - return result; } + /** + * Displays a whole list of registered members + * + * @return list of registered members + */ + public String toString() { + if (listMember.isEmpty()) { + return "There are currently no registered members :("; + } + String ret = "\nRegistered members:\n"; + int counter = 1; + for (Member m : listMember) { + ret += counter + ". " + m.toString() + "\n"; + counter++; + } + return ret.trim(); + } + /** * @param args */ @@ -303,5 +292,4 @@ public class SocialNetwork implements ISocialNetwork { // TODO Auto-generated method stub } - -} \ No newline at end of file +} diff --git a/src/tests/ConsultItemBookTest.java b/src/tests/ConsultItemBookTest.java index fdf87b7b86f824d633370ceb279230c8b9bbb98b..825e35d3503eb61ea47381630ebc82f3027620db 100644 --- a/src/tests/ConsultItemBookTest.java +++ b/src/tests/ConsultItemBookTest.java @@ -1,79 +1,132 @@ package tests; -import opinion.SocialNetwork; +import exceptions.*; import opinion.ISocialNetwork; -import exceptions.BadEntryException; -import exceptions.ItemBookAlreadyExistsException; -import exceptions.MemberAlreadyExistsException; -import exceptions.NotMemberException; +import opinion.SocialNetwork; import java.util.LinkedList; +/** + * Tests for the <i>consultItems()</i> method. + */ public class ConsultItemBookTest { - private static int nbTests = 0; - private static int nbErrors = 0; - - private static void displaySuccess(String message) { - System.out.println("Test passed: " + message); - } - - private static void displayError(String message) { - System.out.println("Test failed: " + message); - nbErrors++; - } - - private static void testExpectedException(ISocialNetwork sn, String title, Class<?> expectedException, String testId) { - nbTests++; + /** + * Checks that consultItems() throws the expected exception. + * + * @param sn the social network + * @param title the title to consult + * @param expectedException the expected exception class (with any type of class) + * @param testId the test identifier + * @return 0 if test is OK, 1 if not OK + */ + private static int checkConsultItemBookException(ISocialNetwork sn, String title, Class<?> expectedException, String testId) { try { sn.consultItems(title); - displayError("[" + testId + "] Expected exception " + expectedException.getSimpleName() + " but none was thrown"); + System.out.println("Err " + testId + " : Expected exception " + expectedException.getSimpleName() + " was not thrown"); + return 1; } catch (Exception e) { if (e.getClass().equals(expectedException)) { - displaySuccess("[" + testId + "] Correctly threw " + expectedException.getSimpleName()); + return 0; } else { - displayError("[" + testId + "] Unexpected exception: " + e); + System.out.println("Err " + testId + " : Unexpected exception " + e); + e.printStackTrace(); + return 1; } } } - private static void testConsultResult(ISocialNetwork sn, String title, int expectedSize, String testId) { - nbTests++; + /** + * Checks that consultItems() returns the expected number of results. + * + * @param sn the social network + * @param title the title to consult + * @param expectedSize the expected number of returned results + * @param testId the test identifier + * @return 0 if test is OK, 1 if not OK + */ + private static int checkConsultItemBookResult(ISocialNetwork sn, String title, int expectedSize, String testId) { try { LinkedList<String> results = sn.consultItems(title); if (results.size() == expectedSize) { - displaySuccess("[" + testId + "] Returned expected number of results: " + expectedSize); + return 0; } else { - displayError("[" + testId + "] Expected " + expectedSize + " but got " + results.size()); + System.out.println("Err " + testId + " : Expected " + expectedSize + " result(s) but got " + results.size()); + return 1; } } catch (Exception e) { - displayError("[" + testId + "] Unexpected exception: " + e); + System.out.println("Err " + testId + " : Unexpected exception " + e); + e.printStackTrace(); + return 1; } } - public static void main(String[] args) { + /** + * Main test for consultItems: + * Checks if the method throws BadEntryException in non-nominal conditions + * Checks if the method works correctly in nominal conditions + * + * @return a summary of the performed tests + */ + public static TestReport test() { ISocialNetwork sn = new SocialNetwork(); + int nbTests = 0; + int nbErrors = 0; try { - sn.addMember("user1", "pass1234", "profile"); - sn.addItemBook("user1", "pass1234", "Don Quijote", "Novela", "Cervantes", 800); - sn.addItemBook("user1", "pass1234", "El Principito", "Fábula", "Saint-Exupéry", 100); - sn.addItemBook("user1", "pass1234", "Principios de Física", "Ciencia", "Tipler", 1200); - } catch (Exception e) { + sn.addMember("User1", "pass1234", "profile"); + sn.addItemBook("User1", "pass1234", "Don Quijote", "Novela", "Cervantes", 800); + sn.addItemBook("User1", "pass1234", "El Principito", "Fábula", "Saint-Exupéry", 100); + sn.addItemBook("User1", "pass1234", "Principios de Física", "Ciencia", "Tipler", 1200); + } catch (BadEntryException | MemberAlreadyExistsException | NotMemberException | + ItemBookAlreadyExistsException e) { System.out.println("Setup failed: " + e); - return; + e.printStackTrace(); + return null; } - // Exception cases - testExpectedException(sn, null, BadEntryException.class, "3.8"); - testExpectedException(sn, " ", BadEntryException.class, "3.9"); - testExpectedException(sn, "a", BadEntryException.class, "3.10"); + System.out.println("Testing consultItems()"); + + // Non-nominal scenarios - // Success cases - testConsultResult(sn, "princip", 2, "3.11"); // It returns two books "El principito" and "Principios de la fisica" - testConsultResult(sn, "DON", 1, "3.12"); // test case-sensitive - testConsultResult(sn, "XYZ", 0, "3.13"); // no results + // Test 3.11 : Uninstantiated title + nbTests++; + nbErrors += checkConsultItemBookException(sn, null, BadEntryException.class, "3.11"); + + // Test 3.12 : Invalid title (only containing a space) + nbTests++; + nbErrors += checkConsultItemBookException(sn, " ", BadEntryException.class, "3.12"); - System.out.println("\nConsultItemBookTest: " + nbTests + " tests run, " + nbErrors + " errors."); + // Test 3.13 : Invalid title (too short) + nbTests++; + nbErrors += checkConsultItemBookException(sn, "a", BadEntryException.class, "3.13"); + + // Nominal scenarios + + // Test 3.14 : Matches "El Principito" and "Principios de Física" + nbTests++; + nbErrors += checkConsultItemBookResult(sn, "princip", 2, "3.14"); + + // Test 3.15 : Matches "Don Quijote" case-insensitively + nbTests++; + nbErrors += checkConsultItemBookResult(sn, "DON", 1, "3.15"); + + // Test 3.16 : No matches + nbTests++; + nbErrors += checkConsultItemBookResult(sn, "XYZ", 0, "3.16"); + + // Print a summary of the tests and return test results + try { + TestReport tr = new TestReport(nbTests, nbErrors); + System.out.println("ConsultItemBookTest : " + tr); + return tr; + } catch (NotTestReportException e) { + System.out.println("Unexpected error in ConsultItemBookTest test code - Can't return valuable test results"); + return null; + } + } + + public static void main(String[] args) { + test(); } } diff --git a/src/tests/ReviewItemBookTest.java b/src/tests/ReviewItemBookTest.java index 744af09506ad9aafa2f7a6b56089f57cfeeb0a49..327b417d8241a061f92dcf11733231a18af95fef 100644 --- a/src/tests/ReviewItemBookTest.java +++ b/src/tests/ReviewItemBookTest.java @@ -1,79 +1,143 @@ package tests; -import opinion.SocialNetwork; +import exceptions.BadEntryException; +import exceptions.NotItemException; +import exceptions.NotMemberException; +import exceptions.NotTestReportException; import opinion.ISocialNetwork; -import exceptions.*; +import opinion.SocialNetwork; +/** + * Tests for the SocialNetwork.<i>reviewItemBook()</i> method. + */ public class ReviewItemBookTest { - private static int nbTests = 0; - private static int nbErrors = 0; - - private static void displaySuccess(String message) { - System.out.println("Test passed: " + message); - } - - private static void displayError(String message) { - System.out.println("Test failed: " + message); - nbErrors++; - } - - private static void testExpectedAverage(ISocialNetwork sn, String login, String password, String title, - float mark, String comment, float expectedAverage, String testId) { - nbTests++; + /** + * Checks that reviewItemBook() returns the expected average after adding a review. + * + * @param sn the social network + * @param login the login of the reviewing member + * @param password the password of the reviewing member + * @param title the title of the book + * @param mark the rating given + * @param comment the comment provided + * @param expectedAverage the expected average rating + * @param testId the test identifier + * @return 0 if test is OK, 1 if not OK + */ + private static int checkReviewItemBookAverage(ISocialNetwork sn, String login, String password, String title, float mark, String comment, float expectedAverage, String testId) { try { float result = sn.reviewItemBook(login, password, title, mark, comment); if (Math.abs(result - expectedAverage) < 0.01f) { - displaySuccess("[" + testId + "] Average = " + result); + return 0; } else { - displayError("[" + testId + "] Expected " + expectedAverage + " but got " + result); + System.out.println("Err " + testId + " : Expected average " + expectedAverage + " but got " + result); + return 1; } } catch (Exception e) { - displayError("[" + testId + "] Unexpected exception: " + e); + System.out.println("Err " + testId + " : Unexpected exception " + e); + e.printStackTrace(); + return 1; } } - private static void testExpectedException(ISocialNetwork sn, String login, String password, String title, - float mark, String comment, Class<?> expectedException, String testId) { - nbTests++; + /** + * Checks that reviewItemBook() throws the expected exception in invalid situations. + * + * @param sn the social network + * @param login the login of the reviewer + * @param password the reviewer's password + * @param title the book's title + * @param mark the rating + * @param comment the review comment + * @param expectedException the expected exception class + * @param testId the test identifier + * @return 0 if test is OK, 1 if not OK + */ + private static int checkReviewItemBookException(ISocialNetwork sn, String login, String password, String title, float mark, String comment, Class<?> expectedException, String testId) { try { sn.reviewItemBook(login, password, title, mark, comment); - displayError("[" + testId + "] Expected exception " + expectedException.getSimpleName() + " but none was thrown"); + System.out.println("Err " + testId + " : Expected exception " + expectedException.getSimpleName() + " was not thrown"); + return 1; } catch (Exception e) { if (e.getClass().equals(expectedException)) { - displaySuccess("[" + testId + "] Correctly threw " + expectedException.getSimpleName()); + return 0; } else { - displayError("[" + testId + "] Unexpected exception: " + e); + System.out.println("Err " + testId + " : Unexpected exception " + e); + e.printStackTrace(); + return 1; } } } + /** + * Main test method for reviewItemBook: + * Tests both nominal and non-nominal scenarios. + * + * @return a summary of the performed tests + */ public static TestReport test() { ISocialNetwork sn = new SocialNetwork(); + int nbTests = 0; + int nbErrors = 0; try { - sn.addMember("ana", "pass123", "casual reader"); - sn.addMember("luis", "1234pass", "fantasy reader"); - sn.addItemBook("ana", "pass123", "El Hobbit", "Fantasía", "J.R.R. Tolkien", 300); + sn.addMember("Neva", "pass123", "casual reader"); + sn.addMember("Maryam", "1234pass", "fantasy reader"); + sn.addItemBook("Neva", "pass123", "El Hobbit", "Fantasía", "J.R.R. Tolkien", 300); } catch (Exception e) { - System.out.println("Setup failed: " + e.getMessage()); + System.out.println("Setup failed: " + e); + e.printStackTrace(); return null; } - // --- Sucess cases --- - testExpectedAverage(sn, "ana", "pass123", "El Hobbit", 4.0f, "So good", 4.0f, "1.1"); - testExpectedAverage(sn, "luis", "1234pass", "El Hobbit", 5.0f, "excelent!", 4.5f, "1.2"); - testExpectedAverage(sn, "ana", "pass123", "El Hobbit", 3.0f, "good but long", 4.0f, "1.3"); + System.out.println("Testing reviewItemBook()"); + + // Non-nominal cases + + // Test 3.1 : Member doesn't exist + nbTests++; + nbErrors += checkReviewItemBookException(sn, "Mario", "nopass", "El Hobbit", 4.0f, "Hola", NotMemberException.class, "3.1"); + + // Test 3.2 : Book title doesn't exist + nbTests++; + nbErrors += checkReviewItemBookException(sn, "Neva", "pass123", "Book X", 3.0f, "Does not exist", NotItemException.class, "3.2"); + + // Test 3.3 : Invalid mark (out of range) + nbTests++; + nbErrors += checkReviewItemBookException(sn, "Neva", "pass123", "El Hobbit", 6.0f, "Out of range", BadEntryException.class, "3.3"); + + // Test 3.4 : Invalid login (empty) + nbTests++; + nbErrors += checkReviewItemBookException(sn, "", "pass123", "El Hobbit", 4.0f, "Fantastic book", BadEntryException.class, "3.4"); + + // Test 3.5 : Invalid password (too short) + nbTests++; + nbErrors += checkReviewItemBookException(sn, "Neva", "a", "El Hobbit", 4.0f, "Fantastic book", BadEntryException.class, "3.5"); + + // Test 3.6 : Invalid book title (empty) + nbTests++; + nbErrors += checkReviewItemBookException(sn, "Neva", "pass123", "", 4.0f, "Fantastic book", BadEntryException.class, "3.6"); - // --- Cases with exception --- - testExpectedException(sn, "mario", "nopass", "El Hobbit", 4.0f, "Hola", NotMemberException.class, "3.1"); - testExpectedException(sn, "ana", "pass123", "Book X", 3.0f, "Does not exist", NotItemException.class, "3.2"); - testExpectedException(sn, "ana", "pass123", "El Hobbit", 6.0f, "Out of range", BadEntryException.class, "3.3"); - testExpectedException(sn, "", "pass123", "El Hobbit", 4.0f, "Fantastic book", BadEntryException.class, "3.4"); - testExpectedException(sn, "ana", "a", "El Hobbit", 4.0f, "Fantastic book", BadEntryException.class, "3.5"); - testExpectedException(sn, "ana", "pass123", "", 4.0f, "Fantastic book", BadEntryException.class, "3.6"); - testExpectedException(sn, "ana", "pass123", "El Hobbit", 4.0f, null, BadEntryException.class, "3.7"); + // Test 3.7 : Uninstantiated comment + nbTests++; + nbErrors += checkReviewItemBookException(sn, "Neva", "pass123", "El Hobbit", 4.0f, null, BadEntryException.class, "3.7"); + + // Nominal cases + + // Test 3.1 : First review for "El Hobbit", expects average mark of 4.0 + nbTests++; + nbErrors += checkReviewItemBookAverage(sn, "Neva", "pass123", "El Hobbit", 4.0f, "So good", 4.0f, "3.8"); + + // Test 3.2 : Second review from another user, expects average of (4.0 + 5.0) ÷ 2 = 4.5 + nbTests++; + nbErrors += checkReviewItemBookAverage(sn, "Maryam", "1234pass", "El Hobbit", 5.0f, "Perfect", 4.5f, "3.9"); + + // Test 3.3: Update Neva's review to 3.0, expects average of (3.0 + 5.0) ÷ 2 = 4.0 + nbTests++; + nbErrors += checkReviewItemBookAverage(sn, "Neva", "pass123", "El Hobbit", 3.0f, "Good but too long", 4.0f, "3.11"); + // Print a summary of the tests and return test results try { TestReport report = new TestReport(nbTests, nbErrors); System.out.println("ReviewItemBookTest : " + report); @@ -87,4 +151,4 @@ public class ReviewItemBookTest { public static void main(String[] args) { test(); } -} +} \ No newline at end of file