Написание юнит-тестов и функций для управления библиотекой - PullRequest
0 голосов
/ 15 марта 2020

Мне было поручено написать C программное обеспечение для управления библиотекой. Пользователи должны иметь возможность регистрироваться, входить в систему, искать книги, брать и возвращать их и, если они библиотекарь, добавлять и удалять книги из библиотеки. Состояние библиотеки (книги, пользователи, ссуды) должно быть сохранено в файл (я думал о создании для книг и один для пользователей). Я получил book_management.h, который не должен быть изменен, и необходимо написать остальную часть программы а также модульные тесты для функций самостоятельно. У меня были проблемы с тем, что ни одна из функций не могла пройти, хотя я думаю, что мой резонанс в порядке, и я не уверен, что речь идет о реализации моих функций или тестах единства, которые я написал. Буду признателен за любые решения, как это исправить.

Определения из book_management.h

#ifndef BOOK_MANAGEMENT_GUARD__H
#define BOOK_MANAGEMENT_GUARD__H

#include <stdio.h>

struct Book {
        char *title; //book title
        char *authors; //comma separated list of authors
        unsigned int year; // year of publication
        unsigned int copies; //number of copies the library has

        unsigned int status; //to tell whether it has been borrowed - 1 for borrowed, 0 if in library
};

struct BookArray {
     struct Book* array; // pointer to array of struct Book.
     unsigned int length; // number of elements in the struct Book * BookArray::find_book_by_author(const char* title)
};
//saves the database of books in the specified file
//returns 0 if books were stored correctly, or an error code otherwise
int store_books(FILE *file);

//loads the database of books from the specified file
//the file must have been generated by a previous call to store_books()
//returns 0 if books were loaded correctly, or an error code otherwise
int load_books(FILE *file);

//adds a book to the ones available to the library
//returns 0 if the book could be added, or an error code otherwise

int add_book (struct Book book);

//removes a book from the library
//returns 0 if the book could be successfully removed, or an error code otherwise.
int remove_book(struct Book book);

//finds books with a given title.
//returns a BookArray structure, where the field "array" is a newly allocated array of books, or null if no book with the
//provided title can be found. The length of the array is also recorded in the returned structure, with 0 in case
//array is the null pointer.
struct BookArray find_book_by_title (const char *title);

//finds books with the given authors.
//returns a BookArray structure, where the field "array" is a newly allocated array of books, or null if no book with the
//provided title can be found. The length of the array is also recorded in the returned structure, with 0 in case
//array is the null pointer.
struct BookArray find_book_by_author (const char *author);

//finds books published in the given year.
//returns a BookArray structure, where the field "array" is a newly allocated array of books, or null if no book with the
//provided title can be found. The length of the array is also recorded in the returned structure, with 0 in case
//array is the null pointer.
struct BookArray find_book_by_year (unsigned int year);

#endif

Определение структуры User от user.h

#define MaxBorrowed 5

struct User {
    char* register_name;
    unsigned int login; //unique for each
    unsigned int status; // librarian (special user) has status 0, others have 1
    unsigned int numberBorrowed;
    struct Book books_borrowed[MaxBorrowed]; //array of books borrowed by the user
};

//
struct UserArray {
    struct User* array; //pointer to an array of struct User
    unsigned int length; //length of an array of struct User

};

book_management. ч

#include "book_management.h"
#include "library.h"
#include "books.csv"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


#define MaxBooksLibrary 1000
 struct Book library_books[MaxBooksLibrary];
 struct BookArray lib_array;


int store_books(FILE *file) //?
{/*
/* we open the file to write binary 
    file = fopen("books.bin", "wb");
    if (file == 0) {
        return -1;
    }
    int i;

    /* write array size */
    //fwrite(&(books_in_lib), sizeof(int), 1, file);

    /* go through array and write each property of the struct file 
    for (i = 0; i<books_in_lib(); i++)
    {
    fwrite(&library_books[i].title, 50 * sizeof(char), 1, file);
    fwrite(&library_books[i].authors, 50 * sizeof(char), 1, file);
    fwrite(&library_books[i].year, sizeof(int), 1, file);
    fwrite(&library_books[i].copies, sizeof(int), 1, file);
    fwrite(&library_books[i].status, sizeof(int), 1, file);
    }

    /*close the file 
    fclose(file);
    return 0;
/*
 //open the  file 
    file = fopen("books.bin", "w");
  int c;
    if( file == NULL)
    {
        printf("Unable to open file '%s'\n",file);
        exit(1);
    }
  char data[500];
  for (int i=0; i<books_in_lib(); i++)
{
  fgets(data, 500, );
  fputs(data, file);
}
  fclose(file);

  return 0;
*/

}

int load_books(FILE *file)
{ 
  char *field;
  int i=0;
  //open the CSV file 
    file = fopen("books.csv","r");
    if(file == NULL)
    {
        printf("Unable to open file '%s'\n",file);
        exit(1);
    }
  char characters[400];
   //  process the data 
//   the file contains 6 fields in a specific order:
//     title,authors,year,copies,status, id
//     separated by commas 
for (int i=0; i<librarySize; i++)
{
    while(fgets(characters,400,file)) //need to write function getline() to jump to the next row while reading the cvs file
    {
    //get title
        field=strtok(characters,",");
        library_books[i].title=malloc(strlen(field)+1);
    strcpy(library_books[i].title, field);
    //  get authors 
        field=strtok(NULL,",");
        library_books[i].authors=malloc(strlen(field)+1);
    strcpy(library_books[i].authors, field);
    // get year 
        field=strtok(NULL,",");
        library_books[i].year=atoi(field);
//  get copies
        field=strtok(NULL,",");
        library_books[i].copies=atoi(field);
    // get status
        field=strtok(NULL,",");
        library_books[i].status=atoi(field);
    //i++;
    }

}
    // close file 
    fclose(file);
  return 0;
  */


}

int add_book (struct Book book)
{
 // FILE*f;
  //load_books(f);
  for (int i=0; i<lib_array.length; i++)
  {
    if (strcmp(library_books[i].title, NULL)==0 && strcmp(library_books[i].authors, NULL)==0 && library_books[i].year==0 && library_books[i].copies==0 && library_books[i].status==0)
    {
      strcpy(library_books[books_in_lib()-1].title,book.title);
      strcpy(library_books[books_in_lib()-1].authors,book.authors);
      library_books[books_in_lib()-1].year=book.year;
      library_books[books_in_lib()-1].copies=book.copies;
      library_books[books_in_lib()-1].status=book.status;
      lib_array.length++;
      break; //don't add the book multiple times
    }
 }
  //now go again through library and update info about copies
  for (int i=0; i<lib_array.length; i++)
  {
    if (strcmp(library_books[i].title, book.title)==0 && strcmp(library_books[i].authors,book.authors)==0 )
    {
      library_books[i].copies++;
    }
  }
  return 0;

}

int remove_book(struct Book book)
{
  FILE*f;
  load_books(f);
  for (int i=0; i<lib_array.length; i++)
  {
    if (strcmp(library_books[i].title, book.title)==0 && strcmp(library_books[i].authors,book.authors)==0 )
    {
      book.copies--;
      library_books[i].copies--;
      library_books[i].title=NULL;
      library_books[i].authors= NULL;
      library_books[i].year=0; 
      library_books[i].copies=0; 
      library_books[i].status=0;
      lib_array.length--;


    }

  }
  //now go again through library and update info about copies
  for (int i=0; i<lib_array.length; i++)
  {
    if (strcmp(library_books[i].title, book.title)==0 && strcmp(library_books[i].authors,book.authors)==0)
    {
      library_books[i].copies--;
    }
  }
  return 0;

}


struct BookArray find_book_by_title (const char *title)
{

  struct BookArray foundArray;
  struct Book found[MaxBooksLibrary];
  int c=0;
  for (int i=0; i<lib_array.length; i++)
  {
    if (strcmp(library_books[i].title,title)==0)
    {
      strcpy(found[i].title,library_books[i].title);
      strcpy(found[i].authors,library_books[i].authors);
      found[i].year=library_books[i].year;
      found[i].copies=library_books[i].copies;
      found[i].status=library_books[i].status;
      foundArray.length++;
    }
  }
  foundArray.array=&found[0];
  return foundArray;

}

struct BookArray find_book_by_author (const char *author)
{
  struct BookArray foundArray;
  struct Book found[MaxBooksLibrary];
  for (int i=0; i<lib_array.length; i++)
  {
    if (strcmp(library_books[i].authors,author)==0) //there might have been multiple authors?
    {
      strcpy(found[i].title,library_books[i].title);
      strcpy(found[i].authors,library_books[i].authors);
      found[i].year=library_books[i].year;
      found[i].copies=library_books[i].copies;
      found[i].status=library_books[i].status;
      foundArray.length++;
    }
  }
  foundArray.array=&found[0];
  return foundArray;

}

struct BookArray find_book_by_year (unsigned int year)
{
  struct BookArray foundArray;
  struct Book found[MaxBooksLibrary];

  for (int i=0; i<lib_array.length; i++)
  {
    if (library_books[i].year==year)
    {
      strcpy(found[i].title,library_books[i].title);
      strcpy(found[i].authors,library_books[i].authors);
      found[i].year=library_books[i].year;
      found[i].copies=library_books[i].copies;
      found[i].status=library_books[i].status;
      foundArray.length++;
    }
  }
  foundArray.array=&found;
  return foundArray;
}



int borrow_book(struct User user, struct Book book)
{
/*
  for (int i=0; i<lib_array.length; i++)
  {
    if (strcpy(library_books[i].title,book.title)==0 && user.numberBorrowed<5 && library_books[i].status==0)
    {
      library_books[i].status=1;
      user.books_borrowed[user.numberBorrowed-1]=book;

      for (int j=0; j<lib_array.length; j++)
      {
        if (strcpy(library_books[j].title,book.title)==0)
        {
        library_books[j].copies--;
        }
      }
      return 0;
    }
  }
}

int return_book(struct User user, struct Book book)
{
  /*
  for (j=0; i<MaxBorrowed; j++)
  {
  if (strcmp(user.books_borrowed[j].title,book.title)==0)
    {
      strcpy(user.books_borrowed[j].title,NULL)==0 && strcpy(user.books_borrowed[j].authors,NULL)==0 && user.books_borrowed[j].year==0 && user.books_borrowed[j].copies==0 && user.books_borrowed[j].status==0
    }
  }

  for (int i=0; i<lib_array.length; i++)
  {
    if (library_books[i].id==book.id)
    {
      library_books[i].status=0;
      for (int j=0; j<books_in_lib(); j++)
      {
      if (strcmp(library_books[j].title,book.title) && strcmp(library_books[j].authors,book.authors) && library_books[j].year==book.year)
        {
          library_books[j].copies++;
        }
      }
      return 0;
    }
  }


}

ЕДИНИЦЫ тесты

#include "unity.h"


#include "book_management.h"
#include "users.h"
#include "library.h"

#include <stdio.h>


void test_store_books() 
{
    FILE* f;
    TEST_ASSERT_NOT_NULL_MESSAGE (f, "There's no such file");
    TEST_ASSERT_MESSAGE(0==store_books(f), "Books were not stored properly in the file");


}

void test_load_books() 
{
    FILE* f;
    TEST_ASSERT_NOT_NULL_MESSAGE (f, "There's no such file");
    TEST_ASSERT_MESSAGE(0==load_books(f), "Books were not loaded properly from the file");


}


void test_add_books() 
{
    struct Book book ={"Harry Potter", "J.K. Rowling", 1997, 3, 0};
    unsigned int prevCopies = book.copies;

    TEST_ASSERT_MESSAGE(0==add_book(book), "Book was not added properly to the library");
    TEST_ASSERT_MESSAGE(book.copies==prevCopies+1, "Wrong number of books in the library");



}

void test_remove_books() 
{
    struct Book book = {"Harry Potter", "J.K. Rowling", 1997, 3, 0};
    unsigned int prevCopies = book.copies;
    TEST_ASSERT_MESSAGE(0==remove_book(book), "Book was not removed properly to the library");
    TEST_ASSERT_MESSAGE(book.copies==prevCopies-1, "Wrong number of books in the library"); 

    /


}

void test_find_book_by_title() 
{

    struct Book book = {"Hobbit", "J.R.R.Tolkien", 1937, 3, 0};

    struct BookArray a = find_book_by_title(book.title);

    TEST_ASSERT_EQUAL_INT_MESSAGE(3, a.length, "Wrong number of books was found");

}

void test_find_book_by_author()
{
    char* author = "J.R.R.Tolkien";
    struct Book book1 = {"Hobbit", "J.R.R.Tolkien", 1937, 3, 0};
    struct Book book2 = {"Lord of the Rings", "J.R.R.Tolkien", 1954 ,5, 0};
    struct Book book3 = {"Silmarillion", "J.R.R.Tolkien", 1977 , 1, 0};
    add_book(book1);
    add_book(book2);
    add_book(book3);
    struct BookArray a = find_book_by_author(author);

    TEST_ASSERT_EQUAL_INT_MESSAGE(9, a.length, "Wrong number of books was found");



}

void test_find_book_by_year()
{
    int year = 1937;
    struct Book book1 = {"Hobbit", "J.R.R.Tolkien", 1937, 3, 0};
    struct Book book2 = {"Of Mice and Men", "John Steinbeck", 1937, 2, 0};
    struct Book book3 = {"Death on the Nile", "Agatha Christie", 1937, 6, 0};
    add_book(book1);
    add_book(book2);
    add_book(book3);
    struct BookArray a = find_book_by_year(year);
    TEST_ASSERT_EQUAL_INT_MESSAGE(11, a.length, "Wrong number of books was found");


}


void test_store_users()
{
    FILE* f;

    TEST_ASSERT_MESSAGE(0==store_users(f), "Users's data was not stored properly in the file");
}

void test_load_users()
{
    FILE* f;

    TEST_ASSERT_MESSAGE(0==load_users(f), "Users' data was not loaded properly from the file");
}

void test_register_new_user()
{
    struct User user;

    TEST_ASSERT_MESSAGE(0==register_new_user(user), "New user has not been registered properly");

}

void test_log_in()
{
    struct User user;

    TEST_ASSERT_MESSAGE(0==log_in(user), "New user has not been registered properly");

}

void test_find_user_by_name()
{
    struct User u;
    TEST_ASSERT_MESSAGE(0!=find_user_by_name(u.register_name), "Function find_user_by_name didn't return a pointer");
}

void test_borrow_book() {
    struct Book book= {"Hobbit", "J.R.R.Tolkien", 1937, 3, 0};
    struct User user;
    user.register_name = "John";
    user.login = 232323;
    user.status = 0;
    user.books_borrowed[MaxBorrowed];
    TEST_ASSERT_MESSAGE(0==borrow_book(user, book), "The books hasn't been borrowed");
}

void test_return_book() {
    struct Book book= {"Hobbit", "J.R.R.Tolkien", 1937, 3, 0};
    struct User user;
    user.register_name = "John";
    user.login = 232323;
    user.status = 0;
    user.books_borrowed[MaxBorrowed];
    TEST_ASSERT_MESSAGE(0==borrow_book(user, book), "The book has not been returned");
}

void setUp() {
     //this function is called before each test, it can be empty
}

void tearDown() {
     //this function is called after each test, it can be empty
}

int main() {
    UNITY_BEGIN();

    RUN_TEST(test_store_books);
    RUN_TEST(test_load_books);
    RUN_TEST(test_add_books);
    RUN_TEST(test_remove_books);
    RUN_TEST(test_find_book_by_title);
    RUN_TEST(test_find_book_by_author);
    RUN_TEST(test_find_book_by_year);

    RUN_TEST(test_store_users);
    RUN_TEST(test_load_users);
    RUN_TEST(test_register_new_user );
    RUN_TEST(test_log_in);

    RUN_TEST(test_borrow_book);
    RUN_TEST(test_return_book);

    RUN_TEST(test_find_user_by_name);

    return UNITY_END();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...