Skip to content

Design and Implementation

JaehoNam edited this page Dec 17, 2019 · 83 revisions

2019/12/17 version 2.00

System Architecture

스크린샷 2019-12-17 오후 4 08 44

Our project consists of frontend and backend, and it will depend on external services for some features. Page view will be implemented with React, along with Redux for shared actions and states among components. Backend will be built using Django, with model being MySQL. Google Map and Azure Text Analyzer services will be used to provide and support some of our services.


Model

This is a schema diagram based on Django. Each rectangle stands for one Django model and each pair of variable name and type in the model stands for field. The first one of those pairs is primary key of that model.

The JSONfield is referenced by https://django-mysql.readthedocs.io/en/latest/model_fields/json_field.html. Our user model will contain this for saving the taste of each user.

View

View

1. Introduce Page (/introduce)


  • Unauthorized user can only access this page. If user is logged in, redirect to /main.
  • User can read how our service will work, why he/she should use our service, what our service will offer him/her.
  • when user clicks Login button...
  • open Login Modal
  • when user clicks Signup button...
  • open Signup Modal
  • when user clicks how/why/what tab, scroll down automatically to proper location of page.

2. Signup Modal


  • User can register new account
    • ID, password, password confirmation, nickname are essential inputs. Others are optional.
    • When the input is invalid, popup automatically appears and notifies how the input should be.

    • When the user submitted with duplicated username or nickname, the error message appears.

    • When user successfully signed up, create new account and the modal closes.

3. Login Modal


  • User can login and go to main page
  • User should put correct ID and password to log in
  • When user click Login button...
    • if ID and password match...
      • Go to main page
    • else...

      • Message that indicates ID or password is wrong appears.
  • When user clicks Register button...
    • Opens signup modal.

4. Main page(/main)


  • Users can see their reviews in various ways.
    • Default
      • User can see his/her reviews in order of LIFO. (List in, First out)
    • Calendar

      • If user selects calendar view, user can see reviews in calendar
      • If user clicks specific date...
        • user can see reviews he/she wrote at specific date
      • Date which doesn't consist any reviews are disabled.
    • Location

      • If user selects location view, user can reviews of selected area of map.
      • If user sets specific location of search by moving the marker.
        • user can see all reviews he/she wrote if the map covers the location of restaurant.
    • Category

      • If user selects category view, user can see dropdown list of category, such as Chinese food and Korean food.
      • If user clicks specific type of category, user can see list of reviews corresponding to its type.
  • When user click See Review button…
    • Open the ReviewDetail Modal.

5 View Select Region

  • When user clicks the dropdown menu...

  • User can select the view type by selecting the dropdown menu.

6 Go to Friend's Home

  • When user clicks the dropdown menu...

  • List of friends appears.

  • When user choose one of them, redirect to that user's main page.

7 Find Friend

  • When user search the friends
  • Autocomplete popup appears so that the user can select the user he/she is finding.
  • User can add friends by clicking 'Add' button.
  • When no user is found, notifty it.

8 I Feel Hungry Modal


  • User can see recommendation of restaurants with in 10km range from user's location, based on taste
  • send request to api/recomfsh/:coordinate_val/ , gets list of restaurants
  • In left side of the Modal, there's a bar graph showing user's taste.
  • When user click Back button…
    • Recommendation Taste Modal is closed
  • When user click one of the restaurant...
    • Restaurant Review Modal is opened
  • When user's mouse cursor points one of the bar in the graph
    • value of the bar is shown

9 FormReview Modal (Add Mode)


  • User can upload new review
  • Food Image, Food Category, Food Name, Rating, Content, Restaurant are essential input.
  • User can select category using drop down box.
  • When user clicks drop down box...
    • List of categories are shown
    • When user clicks category...
      • Category is selected and displayed on drop down box.
      • Drop down menu is closed.
    • When user clicks outside the selection menu...
      • Drop down menu is closed.
  • User can search restaurant on google map.
  • When user search on google map...
    • Markers of restaurant and places with food are shown.
    • When user clicks marker...
      • Restaurant field is automatically filled.
      • Restaurant's information is fetched from google map.

  • When user click Back button…
    • Close FormReview Modal.
  • When user click Submit button…
    • If essential inputs are not empty and every inputs meet the conditions…
      • Upload new review
      • Close FormReview Modal.
    • Else…
      • Button is disabled.

9 FormReview Modal (Edit Mode)


  • User can edit existing review
  • Other people's reviews aren't editable
  • Food Category, Food Name, Rating, Content are essential inputs
  • Other inputs aren't editable.
  • Restaurant's location is visible through google map.
  • Data from existing review is loaded when modal is opened.
  • When user click Back button…
    • Close FormReview Modal
  • When user click Submit button…
    • If essential inputs are not empty and every inputs meet the conditions…
      • Edit selected review.
      • Close FormReview Modal
    • Else…
      • Button is disabled.

11 ReviewDetail Modal


  • User can read review in detail
  • Author, date, food name and category is displayed in header.
  • Image of the food, restaurant on google map, restaurant's name, tags, rating, content are shown as contents
  • When user click Back button…
    • ReviewDetail modal is closed
  • When user click Get Recommendation button…
    • Recommendation modal is opened
    • review id is passed to Recommendation modal

12 Recommendation Modal


  • User can select between recommendation by location or recommendation by taste
  • Consist of Recommendation Location Modal trigger button and Recommendation Taste Modal trigger button
  • When user click Back button…
    • Recommendation Modal is closed
  • When user click Recommendation by Location button…
    • Recommendation Location Modal is opened
  • When user click Recommendation by Taste button...
    • Recommendation Taste Modal is opened

13 Recommendation Location Modal


  • User can see recommendation of restaurants with in 1km range from user's location
  • send request to api/review/:review_id/recomloc/:coordinate_val/ , gets list of restaurants
  • In left side of the Modal, Google Map is shown
  • When user click Back button…
    • Recommendation Location Modal is closed
  • When user click one of the restaurant...
    • Restaurant Review Modal is opened

14 Recommendation Taste Modal


  • User can see recommendation of restaurants with in 10km range from user's location, based on taste
  • send request to api/review/:review_id/recomtst/:coordinate_val/ , gets list of restaurants
  • In left side of the Modal, there's a bar graph showing user's taste.
  • When user click Back button…
    • Recommendation Taste Modal is closed
  • When user click one of the restaurant...
    • Restaurant Review Modal is opened
  • When user's mouse cursor points one of the bar in the graph
    • value of the bar is shown

15 Restaurant Review Modal


  • User can see list of reviews in specific restaurant
  • When user click Back button…
    • Restaurant Review Modal is closed
  • When user click one of the review...
    • Review Detail Modal is opened

Controller

This is a diagram of controller. All GET actions get data from corresponding models. On the contrary, other actions(POST, PUT, DELETE) send data to corresponding models. We will transfer data in JSON form.

Implementation Details

Frontend design

Diagram below represents frontend components, actions, and their relationships.

  • Introduce

    • onLoad(): redirect user automatically if user is logged in already.
  • Signup

    • Signup: Modal Trigger

    • Submit: Button

    • requestDict: Dictionary (consists of: id: String, password: String, passwordConfirm: String, nickname: String, age: Number, gender: Character)

    • onSignup(): submit and create new user with given information.

  • Login

    • Login: Modal Trigger

    • dict: Dictionary (consists of id: String, password: String)

    • onLogin(): log in with given information.

  • Main

    • friendId: Number
  • Feed

    • dict: Dictionary (consists of: friendId: Number, id: Number, author: String, menu: String, image: String, rating: Number, date: String, tag: array of Object, isMine: Boolean )
    • onGetAll(): When friendId is -1, get all reviews of user.
    • onGetFriendAll(): Get the all reviews of given friend.
  • RawCalendar

    • dateString: String
    • friendId: Number
  • ReviewPreview

    • id: Number
  • PrivateRoute

    • onLoad(): function
  • Signup description

  • RealCalendar

    • attribute
      • friendId: id
      • review: list
    • function
      • isDisable(date): find whether there's a review in date. If exist, return false, else, return true
  • Category

    • attribute
      • category: Dropdown(list of category)
      • friendId: id
  • RecommendationTag

    • attribute
      • recoms: list of recommendation
      • id: id
      • data: category string
      • user: User
      • recom-tst-button: Modal Trigger button
      • lat: latitude of user location
      • lng: longitude of user location
    • functions
      • onGetAll(lat, lng): Dispatch Action GET_RECOMS_TST. Get a taste based recommendation list on specific category, and store them through reducer.
      • onGetIFH(lat, lng): Dispatch Action GET_RECOMS_IFH. Get a taste based recommendation list on any category, and store them through reducer.
      • getGeoLocation(): get a location of the user
      • recomHandler(): called when recom-tst-button is pushed, get a recommendation list
  • RecommendationLocation

    • attribute
      • recoms: list of recommendation
      • id: id
      • data: category string
      • user: User
      • recom-loc-button: Modal Trigger button
      • lat: latitude of user location
      • lng: longitude of user location
    • functions
      • onGetAll(lat, lng): Dispatch Action GET_RECOMS_LOC. Get a location based recommendation list on specific category, and store them through reducer.
      • getGeoLocation(): get a location of the user
      • recomHandler(): called when recom-loc-button is pushed, get a recommendation list
  • ReviewDetail

    • attribute
      • marker: show marker on given position
      • center: latitude and longitude
      • onClose: function. when inner modal is closed, this function is called to refresh review data
    • functions
      • onGetReview(id): Dispatch Action GET_REVIEW, get review data and store it through reducer. Called when modal is opened or modal inside ReviewDetail is closed.
      • onDeleteReview(id): Dispatch Action DELETE_REVIEW, delete current review. Called when delete button is clicked.
      • loadReview(): Dispatch onGetReview() to get review information, and set ready state to true once it is done. Passed as props to modal components mounted inside ReviewDetail, so details of review could be reloaded.
      • deleteHandler(): Dispatch onDeleteReview() to delete review, and close this modal once it is done.
  • ReviewLocation

    • attribute
      • id: Number,
      • author: String.
      • menu: String,
      • image: String,
      • restaurant: String,
      • content: String,
      • rating: Number,
      • date: String,
      • tag: array of Object,
      • isMine: Boolean
      • marker: show marker on given position
      • center: latitude and longitude
      • draggable: Marker is draggable. Marker's new position will be notified to this component with getInfo() function.
      • getInfo: function. Get marker's new position from GoogleMap.
      • restaurants: Array of restaurants that are reviewed in given area.
  • FormReview

    • attribute
      • search: Props passed to GoogleMap. Enable SearchBox in GoogleMap.
      • center: Map's center position. Marker's default position is set to center position. Consists of latitude and longitude. Passed to GoogleMap as props.
      • getInfo: funtion. Get place api information from GoogleMap.
    • functions
      • onPostReview(): Dispatch Action POST_REVIEW, post review data through backend API and store it through reducer. Called when submit button is active and clicked, and modal is on 'ADD' mode.
      • onEditReview(): Dispatch Action EDIT_REVIEW, edit review data through backend API and store it through reducer. Called when submit button is active and clicked, and modal is on 'EDIT' mode.
      • editContentHandler(): Retrive review data from component state, and dispatch onEditReview() to edit review. Once action is finished, close modal.
      • postContentHandler(): Retrive review data from component state, and dispatch onPostReview() to post review. Once action is finished, close modal.
  • GoogleMap

    • attribute
      • getInfo: Function to get place info including place id, place's name, latitude, longitude to this.
      • mapInstance: Google map's instance. Used as api functions' arguments.
      • mapApi: Google map's API class. API functions are mapped in the class.
  • SearchBox

    • functions
      • onPlacesChanged(): When user searched keyword with SearchBox, places information is retrived and filtered. Markers will be placed with this function. Also map's bounds are adjusted based on places.
  • FriendList

    • attributes

      • redirect-to-friend-main-dropdown: redirect to selected friend's main page
      • handleChange(): if user select him/herself, then redirect to main page, else if user select his/her friend, redirect to friend's main page
    • actions

      • onGetFriends(): Dispatch Action GET_FRIENDS, get all ids and nicknames of friends
  • FriendSearch

    • attributes

      • add-friend-button: Dispatch onAddFriend() to add friend to user's friend list
      • searchUserHandler(): Dispatch onSearchUsers() to search users whose nickname starts with searching keyword
    • actions

      • onSearchUsers: Dispatch Action SEARCH_USERS, get all ids and nicknames of users whose nickname starts with prefix
      • onAddFriend: Dispatch Action ADD_FRIEND, add new friend id to user's friend id list
  • Recommendation

    • attributes
      • data: review's category data (to RecommendLocation, RecommendTag)
      • id: review's id (to RecommendLocation, RecommendTag)
      • recom-modal-trigger-button: redirect to recommendation modal
      • close-recom-modal-button: redirect to review detail modal
      • onClose(): close modal and redirect to previous modal
  • Myinfo

    • actions
      • onGetFriend(): Dispatch Action GET_FRIEND_INFO to show friend's info if friend
  • RestaurantReview

    • attributes

      • res-list-button: call clickHandler() to call onGetAll()
      • clickHandler(): Dispatch onGetAll() to get all review list of restaurant
      • res-list-close-button: redirect to previous modal
      • id: Number,
      • author: String.
      • menu: String,
      • image: String,
      • restaurant: String,
      • content: String,
      • rating: Number,
      • date: String,
      • tag: array of Object,
      • isMine: Boolean
    • actions

      • onGetAll(): Dispatch Action GET_RESTAURANT_REVIEWS to show review list of restaurant
  • Action_User

    • actions
      • GET_USER_INFO: send GET '/api/' to backend, get response, store user information. If it fails, set user state as not logged in and initialize user information through reducer.
      • LOGIN: send POST '/api/signin/' to backend, get response, and set user state as logged in. If it fails set user state as not logged in through reducer.
      • FIND_ID: send POST '/api/signup_dupcheck/' to backend, get response, and store duplicate check result through reducer.
      • REGISTER: send POST '/api/signup/' to backend, get response.
      • LOGOUT: set user state as not logged in and initialize user information through reducer.
      • GET_FRIENDS: send GET '/api/friends/' to backend, get response, and store friends list through reducer.
      • SEARCH_USER: send GET '/api/search_user/${prefix}/' to backend, get response, and store user search list through reducer.
      • ADD_FRIEND: send POST '/api/friends/' to backend, get response, and clean user search result through reducer and dispatch GET_FRIENDS and GET_USER_INFO to update friends information.
      • DELETE_FRIEND: send DELETE '/api/friends/${id}/' to backend, get response, and clean user search result through reducer and dispatch GET_FRIENDS and GET_USER_INFO to update friends information.
      • GET_FRIEND_INFO: send GET '/api/friends/${id}/' to backend, get response, and store friend's information through reducer.
  • Action_Review

    • actions
      • GET_REVIEWS: send GET '/api/review/' to backend, get response, store review list through reducer
      • GET_REVIEW: send GET '/api/review/:id/' to backend, get response, store review detail through reducer
      • DELETE_REVIEW: send DELETE '/api/review/:id/' to backend, from store, find the review with id and delete it.
      • EDIT_REVIEW: send EDIT '/api/review/:id/' to backend, from store, find the review with id and edit it using response from backend.
      • POST_REVIEW: send POST '/api/review/' to backend, get response, add the review to reviewList in store.
      • GET_RESTAURANT_REVIEWS: send GET '/api/restaurant/:id/' to backend, get the reviews of specific restaurant and store it through reducer.
      • GET_FRIEND_REVIEWS: send GET '/api/friend/:id/review/' to backend, get the reviews of specific friend id and store it through reducer.
  • Action_Recom

    • actions
      • GET_RECOMS_LOC: send GET '/api/review/${data.id}/recomloc/c=${data.lat},${data.log}/' to backend, get response, store recommendation by location list. If it fails, clear recomlocList.
      • GET_RECOMS_TST: send GET '/api/review/${data.id}/recomtst/c=${data.lat},${data.log}/' to backend, get response, store recommendation by taste list. If it fails, clear recomtstList.
      • GET_RECOMS_IFH: send GET '/api/recomifh/c=${data.lat},${data.log}/' to backend, get response, store recommendation by taste without category restriction list. If it fails, clear recomtstList.

Backend design

This is Django API for our application.

Model API GET POST PUT DELETE
User api/signup/ X Create new user X X
api/signup_dupcheck/ X Check if username and nickname exists X X
api/signup/:profile_id/image/ X Add profile image X X
api/signin/ X Log in X X
api/signout/ Log out X X X
api/ Get user info X Edit user info X
api/search_user/:nickname/ Find users' nickname starting with nickname X X X
api/friend/ Get friend list Add new friend X X
api/friend/:friend_id/ Get specified friend X X Delete specified friend
Review api/review/ Get review list Create new review X X
api/review/:review_id/ Get specified review X Edit specified review Delete specified review
api/review/:review_id/image/ X Add review image X X
api/friend/:friend_id/review/ Get friend's review list X X X
api/friend/:friend_id/review/:review_id/ Get friend's specified review X X X
Restaurant api/restaurant/:restaurant_id/ Get restaurant review list X X X
Recommendation api/review/:review_id/recomloc/:coordinate_val/ Get location-based recommendation list on specific category, in 1km range from coordinate_val X X X
api/review/:review_id/recomtst/:coordinate_val/ Get taste-based recommendation list on specific category, in 10km range from coordinate_val X X X
api/recomifh/:coordinate_val/ Get taste-based recommendation list on any category, in 10km range from coordinate_val X X X

api/signup/

  • POST
    • require json : {"username": string, "password": string, "nickname": string}
    • (additional) json : {"phone_number": string, "age": int, "gender": string}
    • return json : {"id": id, "username": string, "phone_number": string, "age": int, "gender": string, "number_of_reviews": int, "number_of_friends": int, "nickname": string}
    • KeyError : status 400
    • Success : status 201
  • NotAllowedMethod : status 405

api/signup_dupcheck/

  • POST
    • require json : {"useraname": string, "nickname": string}
    • return json : {"id": id, "id2": id}
    • KeyError : status 400
    • Success : status 200
  • NotAllowedMethod : status 405

api/signup/:profile_id/image/

  • POST
    • require multipart/form-data : "profile_pic": file
    • return json : {"username": string, "phone_number": string, "age": int, "gender": string, "number_of_reviews": int, "number_of_friends": int, "nickname": string}
    • FileError : status 400
    • Success : status 201
  • NotAllowedMethod : status 405

api/signin/

  • POST
    • require json : {"username": string, "password": string}
    • KeyError : status 400
    • Success : status 204
  • AuthenticateError : status 401
  • NotAllowedMethod : status 405

api/signout/

  • GET
    • Success : status 204
  • AuthenticateError : status 401
  • NotAllowedMethod : status 405

api/

  • GET
    • return json response : {"username": string, "phone_number": string, "age": int, "gender": string, "number_of_reviews": int, "number_of_friends": int, "nickname": string, "taste": dict}
    • (additional) json : {"profile_pic": string}
    • Success : status 200
  • PUT
    • (additional) json : {"phone_number": string, "age": int, "gender": string, "nickname": string}
    • return json : {"username": string, "phone_number": string, "age": int, "gender": string, "number_of_reviews": int, "number_of_friends": int, "nickname": string, "taste": dict}
    • KeyError : status 400
    • Success : status 201
  • AuthenticateError : status 401
  • NotAllowedMethod : status 405

api/friend/

  • GET
    • return json list : each element: {"id": int, "nickname": string}
    • Success : status 200
  • POST
    • require json : {"id": int}
    • return json list : each element: {"nickname": string}
    • KeyError : status 400
    • Success : status 204
  • AuthenticateError : status 401
  • NotAllowedMethod : status 405

api/friend/:friend_id/

  • GET
    • return json response : {"username": string, "phone_number": string, "age": int, "gender": string, "number_of_reviews": int, "number_of_friends": int, "nickname": string}
    • (additional) json : {"profile_pic": string}
    • NotFound : status 404
    • Success : status 200
  • DELETE
    • NotFound : status 404
    • Success : status 204
  • AuthenticateError : status 401
  • NotAllowedMethod : status 405

api/search_user/:nickname

  • GET
    • return json list : each element: {"id": int, "nickname": string}
    • Success : status 200
  • AuthenticateError : status 401
  • NotAllowedMethod : status 405

api/review/

  • GET
    • return json list : each element: {'id': id, 'author': string, 'restaurant': string, 'menu': string, 'content': string, 'rating': float, 'image': string, 'date': date("%Y-%m-%d"), 'tag': list_of_string, 'category': string, 'placeid': string, 'longitude': float, 'latitude': float}
    • Success : status 200
  • POST
    • require json : {'restaurant_name': string, 'menu_name': string, 'content': string, 'rating': float, 'category': string, 'placeid': string, 'longitude': float, 'latitude': float}
    • return json : {'id': id, 'author': string, 'restaurant': string, 'menu': string, 'content': string, 'rating': float, 'date': date("%Y-%m-%d"), 'tag': list_of_string, 'category': string, 'placeid': string, 'longitude': float, 'latitude': float}
    • KeyError : status 400
    • Success : status 201
  • AuthenticateError : status 401
  • NotAllowedMethod : status 405

api/review/:review_id/

  • GET
    • return json response : {'id': id, 'author': string, 'restaurant': string, 'menu': string, 'content': string, 'rating': float, 'image': string, 'date': date("%Y-%m-%d"), 'tag': list_of_string, 'category': string, 'placeid': string, 'longitude': float, 'latitude': float}
    • Success : status 200
  • PUT
    • require json : {'restaurant_name': string, 'menu_name': string, 'content': string, 'rating': float, 'category': string, 'placeid': string, 'longitude': float, 'latitude': float}
    • return json : {'id': id, 'author': string, 'restaurant': string, 'menu': string, 'content': string, 'rating': float, 'image': string, 'date': date("%Y-%m-%d"), 'tag': list_of_string, 'category': string, 'placeid': string, 'longitude': float, 'latitude': float}
    • NotFound : status 404
    • Forbidden : status 403
    • KeyError : status 400
    • Success : status 200
  • DELETE
    • NotFound : status 404
    • Forbidden : status 403
    • Success : status 204
  • AuthenticateError : status 401
  • NotAllowedMethod : status 405

api/review/:review_id/image/

  • POST
    • require multipart/form-data : "image": file
    • return json : {'id': id, 'author': string, 'restaurant': string, 'menu': string, 'content': string, 'rating': float, 'image': string, 'date': date("%Y-%m-%d"), 'tag': list_of_string, 'category': string, 'placeid': string, 'longitude': float, 'latitude': float}
    • FileError : status 400
    • Success : status 201
  • AuthenticateError : status 401
  • NotFound : status 404
  • Forbidden : status 403
  • NotAllowedMethod : status 405

api/friend/:friend_id/review/

  • GET
    • return json list : each element: {'id': id, 'author': string, 'restaurant': string, 'menu': string, 'content': string, 'rating': float, 'image': string, 'date': date("%Y-%m-%d"), 'tag': list_of_string, 'category': string, 'placeid': string, 'longitude': float, 'latitude': float}
    • Success : status 200
  • AuthenticateError : status 401
  • NotFound : status 404
  • Forbidden : status 403
  • NotAllowedMethod : status 405

api/friend/:friend_id/review/:review_id

  • GET
    • return json response : {'id': id, 'author': string, 'restaurant': string, 'menu': string, 'content': string, 'rating': float, 'image': string, 'date': date("%Y-%m-%d"), 'tag': list_of_string, 'category': string, 'placeid': string, 'longitude': float, 'latitude': float}
    • NotFound : status 404
    • Forbidden : status 403
    • Success : status 200
  • AuthenticateError : status 401
  • NotFound : status 404
  • Forbidden : status 403
  • NotAllowedMethod : status 405

api/restaurant/:restaurant_id/

  • GET
    • return json list : each element: {'id': id, 'author': string, 'restaurant': string, 'menu': string, 'content': string, 'rating': float, 'image': string, 'date': date("%Y-%m-%d"), 'tag': list_of_string, 'category': string, 'placeid': string, 'longitude': float, 'latitude': float}
    • Success : status 200
  • AuthenticateError : status 401
  • NotAllowedMethod : status 405

api/review/:review_id/recomloc/:coordinate_val/

api/review/:review_id/recomtst/:coordinate_val/

api/recomifh/:coordinate_val/

  • GET
    • return json list : each element: {'id': id, 'name': string, 'longitude': float, 'latitude': float, 'rating': float, 'my_rating': float, 'other_rating': float}
    • Success : status 200
  • AuthenticateError : status 401
  • NotAllowedMethod : status 405

Date format should be YYYY-MM-DD (Leading zero must be included)

Implementation Plan

Page Feature Difficulty Sprints Assignee Challenges
Sign up sign up 0.5 4 남재호(frontend), 최지혁(backend)
Login log in 0.5 4 남재호(frontend), 최지혁(backend)
Login log in with sns 4 4 -> 5 남재호(frontend), 최지혁(backend) SNS link
Main load review_list 1 3 차병희(frontend), 남재호(backend)
Main load calendar 1.5 3 -> 4 차병희(frontend)
Main load location 2 3 -> 4 -> 5, 6 최지혁(frontend), 남재호(backend) Kakao map api
Main load filtered with menu 1.5 3 -> 4 -> 5 -> 6 차병희(frontend)
Main add friend show friends 1.5 4 -> 5 -> 6 강태호(frontend) ,차병희(backend)
User Info account setting 0.5 4 -> 5 남재호(frontend), 최지혁(backend)
User Info show helps 0.1 4 -> 5 남재호(frontend)
Upload add review 1 3 차병희(frontend), 남재호(backend)
Review show review detail 1 3 최지혁(frontend), 강태호(backend)
Recommendation do recommend 5 3, 4, 5 차병희, 최지혁, 강태호, 남재호 Recommendation algorithm
Recommendation show recommendations 1.5 3, 4, 5, 6 강태호, 남재호
Friends show friends' main 1.5 4 -> 5 -> 6 강태호(frontend), 차병희(backend)
CSS 3 5, 6

Testing Plan

We have very tight schedule of each sprint of project. Saving time is very important. Therefore, we decided to use BDD(Behavior-Driven-Design) rather than TDD(Test-Driven-Design) because TDD tends to take more time than BDD. Because TDD tends to reduce more bugs than BDD, we will be careful when writing code to offset such shortcomings. We will make our code coverage up to 80%.

Unit test

Every unit in our service will be tested by following tools

  • React, Redux
    • Jest: Javascript test framework. Jest have intuitive grammar and good mock module such as jest.fn and jest.spyOn. Especially, we can explain about test using describe and it statement which makes code legibility better.
  • Django
    • python.unittest: python test framework. We chose python.unittest because it has intuitive grammar, so it is easy to write a test without bugs. django.test package will also help us.

Functional test

  • Frontend will be tested using jest and enzyme. Each feature will be tested based on user story scenario. Mock will be used to replicate interaction with backend.
  • For backend functional testing, api requests will be simulated based on each scenario. We will use python and django's built-in test library to test our django backend. Client and models will be mocked using feature of django test.

Integration test

  • All user stories should be covered. We will use travis CI for integration test, without human intervention

Revision History