CSC/ECE 517 Spring 2024 - G2402 Implement REST client, REST API, and Graphql API endpoint for repositories - Part 2: Difference between revisions
Line 298: | Line 298: | ||
== Testing == | == Testing == | ||
To ensure the reliability and robustness of the GitHub Miner, comprehensive testing strategies, including unit tests and integration tests, have been implemented. These tests validate the functionality of the API endpoints across different scenarios, ensuring the system's correctness and stability. The testing suite covers the following areas: | <p>To ensure the reliability and robustness of the GitHub Miner, comprehensive testing strategies, including unit tests and integration tests, have been implemented. These tests validate the functionality of the API endpoints across different scenarios, ensuring the system's correctness and stability. The testing suite covers the following areas:</p> | ||
<b>1. Unit Tests:</b> | |||
Unit tests have been developed to test individual components in isolation, ensuring that each part functions correctly on its own. This section details the unit tests for both the GitHub GraphQL integration and specific queries related to GitHub data retrieval: | <p>Unit tests have been developed to test individual components in isolation, ensuring that each part functions correctly on its own. This section details the unit tests for both the GitHub GraphQL integration and specific queries related to GitHub data retrieval:</p> | ||
<b>2. GitHub GraphQL Tests:</b> | |||
<ul> | |||
<li><strong>test_authentication.py</strong>: Ensures robust authentication by testing token handling and refresh mechanisms.</li> | |||
<li><strong>test_client.py</strong>: Validates the GraphQL client's initialization, error handling, and proper response parsing.</li> | |||
<li><strong>test_query.py</strong>: Checks the correct formation, execution, and error handling of GraphQL queries.</li> | |||
</ul> | |||
<b>3. Queries Tests:</b> | |||
<ul> | |||
<li><strong>Comments</strong>: Confirms accurate retrieval and parsing of comments from GitHub repositories.</li> | |||
<li><strong>Contributions</strong>: Verifies the accuracy and completeness of contribution data, including commits and pull requests.</li> | |||
<li><strong>Costs</strong>: Tests accurate cost calculation for managing API rate limits.</li> | |||
<li><strong>Profiles</strong>: Ensures comprehensive fetching and correct parsing of user profiles.</li> | |||
<li><strong>Repositories</strong>: Validates retrieval of detailed repository information.</li> | |||
<li><strong>Time Range Contributions</strong>: Assesses the accuracy of fetching and aggregating contributions within specified time ranges.</li> | |||
</ul> | |||
<b>4. Integration Tests:</b> | |||
Integration tests verify the interaction between different components of the system, ensuring that they work together as expected. These tests are crucial for assessing the seamless operation of front-end to back-end interactions and the overall data flow within the application: | <p>Integration tests verify the interaction between different components of the system, ensuring that they work together as expected. These tests are crucial for assessing the seamless operation of front-end to back-end interactions and the overall data flow within the application:</p> | ||
<ul> | |||
<li><strong>TestClient</strong>: Tests the GitHub client's ability to initialize correctly, generate headers, handle retries, execute queries efficiently, and manage paginated responses.</li> | |||
<li><strong>Authentication Tests</strong>: Validates the generation of correct authorization headers and proper handling of personal access tokens.</li> | |||
</ul> | |||
<b>5. Testing Examples:</b> | |||
<p>Here, we provide specific examples of test cases implemented in our project. You can see how we approach testing for both unit and integration levels, focusing on key functionalities and integration points.</p> | |||
<pre><code> | |||
@pytest.fixture | @pytest.fixture | ||
def valid_token(): | def valid_token(): | ||
Line 353: | Line 348: | ||
class TestClient: | class TestClient: | ||
def test_client_initialization(self, github_client): | def test_client_initialization(self, github_client): | ||
assert github_client._authenticator is not None, "Authenticator should be set." | assert github_client._authenticator is not None, "Authenticator should be set." | ||
</code></pre> | |||
<p>These tests collectively ensure that the GitHub Miner operates reliably, providing accurate and timely data from GitHub's APIs. By covering a wide range of scenarios, from successful queries to error handling and rate limiting, the tests ensure that the application can be used confidently in production environments.</p> | |||
These tests collectively ensure that the GitHub Miner operates reliably, providing accurate and timely data from GitHub's APIs. By covering a wide range of scenarios, from successful queries to error handling and rate limiting, the tests ensure that the application can be used confidently in production environments. | |||
==Live Demo & Source Code== | ==Live Demo & Source Code== |
Revision as of 08:12, 25 April 2024
Project Objective
This project aims to create a robust tool enabling users to access and analyze their GitHub metrics conveniently. The phase one objective was to develop API endpoints leveraging GitHub GraphQL and GitHub REST queries within a Python Flask framework. This involves integrating Flask with existing code to expose GraphQL queries as API endpoints, building a REST client, and establishing REST endpoints for streamlined data retrieval.
Subsequently, in phase two of the project, each API endpoint established in the initial phase will be complemented with a React-based frontend. This frontend will be specifically designed to visualize and present the GitHub data retrieved through these endpoints in an intuitive user interface. The goal is to seamlessly integrate backend functionality with frontend design to enhance user interaction and data presentation.
Below is the MVC architecture of our GitHub project:
Plan of Work
In the second phase of the project, we will focus on developing a robust and user-friendly frontend using React. The frontend will serve as an intuitive interface for displaying and interacting with the data retrieved from the GitHub API endpoints implemented in the first phase.
The plan includes the following key steps:
1. Setup React Environment:
- Selecting Tooling and Libraries: Choose an appropriate React setup such as Create React App for rapid development or Next.js for server-side rendering and enhanced performance.
- Dependency Management: Use npm or Yarn to manage project dependencies, including React, ReactDOM, and additional libraries for state management (Redux, Recoil), routing (React Router), and styling (styled-components, Tailwind CSS).
- Project Structure: Organize the project structure with components, containers, services, and utility folders to maintain a scalable and maintainable codebase.
2. Design UI Components:
- Translate the data from the API endpoints into interactive React components, focusing on usability and accessibility standards.
- Component Composition: Create reusable and composable UI components following component-based design principles, leveraging hooks (useState, useEffect) for managing state and side effects.
- Styling: Implement consistent styling using CSS-in-JS solutions like styled-components or CSS modules, ensuring modular and scoped styles for each component.
3. Integrate with API Endpoints:
- HTTP Requests: Use Axios or Fetch API to handle asynchronous data fetching from the backend API endpoints implemented in phase one.
- State Management: Implement state management (e.g., Redux, Context API) to store and manage fetched data centrally across components, ensuring efficient data flow and reactivity.
- Optimizing Performance: Implement memoization techniques (e.g., useMemo, useCallback) to optimize re-renders and reduce unnecessary API calls.
4. Implement Pagination:
- Pagination Logic: Develop pagination logic to manage and display large datasets in manageable chunks, adhering to RESTful API standards for page-based navigation.
- UI Components: Create pagination controls (e.g., buttons, page indicators) to allow users to navigate through paginated data smoothly, updating the UI dynamically based on user interactions.
5. Enhance User Experience:
- We will focus on improving the user experience by adding features such as search functionality, filtering, sorting, and other relevant enhancements based on the data being displayed. These enhancements will empower users to interact with the data more effectively and derive valuable insights.
- Interactive Visualizations: Integrate interactive charts (e.g., using Chart.js, D3.js) to visually represent data trends and insights, enhancing user engagement and understanding.
6. Test and Debug:
- Unit Testing: Write unit tests using Jest and React Testing Library to ensure individual components render correctly and exhibit expected behavior based on props and state.
- Integration Testing: Conduct integration tests to validate API integrations, data flow, and interactions between frontend components.
- Cross-Browser Compatibility: Perform cross-browser testing (e.g., Chrome, Firefox, Safari) and responsive testing to ensure consistent rendering and functionality across different browsers and devices.
7. Deploy and Document: Finally, we will deploy the React frontend to a hosting platform, ensuring it is accessible and easily usable by end-users. Comprehensive documentation will be provided, including instructions for setup, usage, and any relevant information for future maintenance and development.
Frontend
As shown below, we plan to display contributors' individual contribution and commit count. We will be implementing the UI using ReactJS
Commits page with number of commits
GraphQL Endpoints
Get current user login:
/api/graphql/current-user-login
Sample Output:
{ "viewer": { "login": "<your-username>" } }
Get specific user login:
/api/graphql/user-login/<username>
Get list of all commits in a repo:
/api/graphql/specific-user-commits/<owner>/<repo_name>
Sample Output: {
"repository": { "defaultBranchRef": { "target": { "history": { "nodes": [ { "additions": 0, "author": { "email": "61797592+Atharva7007@users.noreply.github.com", "name": "Atharva Pansare", "user": { "login": "Atharva7007" } }, "authoredDate": "2020-04-03T09:30:17Z", "changedFilesIfAvailable": 1, "deletions": 0, "message": "Add files via upload", "parents": { "totalCount": 1 } } ], "pageInfo": { "endCursor": "98ba34a6c62ff6fe7c4d4de5c342a194f72d66e4 0", "hasNextPage": true }, "totalCount": 6 } } } } },
Get details of all contributors in a repo:
/api/graphql/repository-contributors/<owner>/<repo_name>
Sample Output: {
"repository": { "defaultBranchRef": { "target": { "history": { "nodes": [ { "author": { "email": "61797592+Atharva7007@users.noreply.github.com", "name": "Atharva Pansare", "user": { "login": "Atharva7007" } } } ], "pageInfo": { "endCursor": "98ba34a6c62ff6fe7c4d4de5c342a194f72d66e4 0", "hasNextPage": true }, "totalCount": 6 } } } } }
REST API Endpoints
Get current user login:
/api/rest/current-user-login-rest
This endpoint retrieves the login information of the currently authenticated user. It fetches the user's profile data from the GitHub API and returns details such as their username, avatar URL, and other relevant information.
Sample Output:
{ "avatar_url": "https://avatars.githubusercontent.com/u/61797592?v=4", "bio": null, "blog": "", "company": null, "created_at": "2020-03-04T16:49:06Z", "email": null, "events_url": "https://api.github.com/users/Atharva7007/events{/privacy}", "followers": 1, "followers_url": "https://api.github.com/users/Atharva7007/followers", "following": 3, "following_url": "https://api.github.com/users/Atharva7007/following{/other_user}", "gists_url": "https://api.github.com/users/Atharva7007/gists{/gist_id}", "gravatar_id": "", "hireable": null, "html_url": "https://github.com/Atharva7007", "id": 61797592, "location": null, "login": "Atharva7007", "name": "Atharva Pansare", "node_id": "MDQ6VXNlcjYxNzk3NTky", "organizations_url": "https://api.github.com/users/Atharva7007/orgs", "public_gists": 0, "public_repos": 11, "received_events_url": "https://api.github.com/users/Atharva7007/received_events", "repos_url": "https://api.github.com/users/Atharva7007/repos", "site_admin": false, "starred_url": "https://api.github.com/users/Atharva7007/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/Atharva7007/subscriptions", "twitter_username": null, "type": "User", "updated_at": "2024-03-14T19:03:46Z", "url": "https://api.github.com/users/Atharva7007" }
Get list of all commits in a repo:
/api/rest/specific-user-commits/<owner>/<repo_name>
This endpoint retrieves a list of all commits made to a specific repository. It takes the repository owner and repository name as parameters. The endpoint fetches the commit history from the GitHub API and returns details about each commit, such as the author, commit message, and changes made.
Sample Output:
[ { "repository": { "defaultBranchRef": { "target": { "history": { "nodes": [ { "additions": 0, "author": { "email": "61797592+Atharva7007@users.noreply.github.com", "name": "Atharva Pansare", "user": { "login": "Atharva7007" } }, "authoredDate": "2020-04-03T09:30:17Z", "changedFilesIfAvailable": 1, "deletions": 0, "message": "Add files via upload", "parents": { "totalCount": 1 } } ], "pageInfo": { "endCursor": "98ba34a6c62ff6fe7c4d4de5c342a194f72d66e4 0", "hasNextPage": true }, "totalCount": 6 } } } } } ]
Get details of all contributors in a repo:
/api/rest/repository-contributors/<owner>/<repo_name>
This endpoint fetches the details of all contributors to a specific repository. It takes the repository owner and repository name as parameters. The endpoint retrieves the list of contributors from the GitHub API and returns information about each contributor, such as their username, avatar URL, and permissions within the repository.
Sample Output: [
{ "avatar_url": "https://avatars.githubusercontent.com/u/61797592?v=4", "events_url": "https://api.github.com/users/Atharva7007/events{/privacy}", "followers_url": "https://api.github.com/users/Atharva7007/followers", "following_url": "https://api.github.com/users/Atharva7007/following{/other_user}", "gists_url": "https://api.github.com/users/Atharva7007/gists{/gist_id}", "gravatar_id": "", "html_url": "https://github.com/Atharva7007", "id": 61797592, "login": "Atharva7007", "node_id": "MDQ6VXNlcjYxNzk3NTky", "organizations_url": "https://api.github.com/users/Atharva7007/orgs", "permissions": { "admin": true, "maintain": true, "pull": true, "push": true, "triage": true }, "received_events_url": "https://api.github.com/users/Atharva7007/received_events", "repos_url": "https://api.github.com/users/Atharva7007/repos", "role_name": "admin", "site_admin": false, "starred_url": "https://api.github.com/users/Atharva7007/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/Atharva7007/subscriptions", "type": "User", "url": "https://api.github.com/users/Atharva7007" }
]
Implementation Details
The GitHub Miner project consists of two main components: the backend API and the frontend user interface.
The backend API is implemented using Flask, a lightweight Python web framework. It exposes two sets of endpoints: one for GraphQL queries and another for REST API queries. Flask Blueprints are used to route requests to the appropriate endpoints based on the URL path.
The GraphQL implementation utilizes the `graphene` library, which provides a way to define GraphQL schemas and resolvers. The resolvers are responsible for fetching data from the GitHub API using the `pygithub` library.
The REST implementation uses the `requests` library to make HTTP requests to the GitHub API and process the responses.
To ensure reliability and robustness, comprehensive testing strategies, including unit tests and integration tests, have been implemented. These tests validate the functionality of the API endpoints across different scenarios, ensuring the system's correctness and stability.
In the API, we have 2 separate endpoints to retrieve the same data: one for REST and the other using GraphQL queries. To manage this, we have made use of Flask Blueprints where all the "api/graphql" requests get routed to the graphql variants and the "api/rest" requests get routed to the REST variants.
Design Patterns used
- The REST API Client /backend/app/services/github_query/github_rest/client.py is a Singleton.
Testing
To ensure the reliability and robustness of the GitHub Miner, comprehensive testing strategies, including unit tests and integration tests, have been implemented. These tests validate the functionality of the API endpoints across different scenarios, ensuring the system's correctness and stability. The testing suite covers the following areas:
1. Unit Tests:
Unit tests have been developed to test individual components in isolation, ensuring that each part functions correctly on its own. This section details the unit tests for both the GitHub GraphQL integration and specific queries related to GitHub data retrieval:
2. GitHub GraphQL Tests:
- test_authentication.py: Ensures robust authentication by testing token handling and refresh mechanisms.
- test_client.py: Validates the GraphQL client's initialization, error handling, and proper response parsing.
- test_query.py: Checks the correct formation, execution, and error handling of GraphQL queries.
3. Queries Tests:
- Comments: Confirms accurate retrieval and parsing of comments from GitHub repositories.
- Contributions: Verifies the accuracy and completeness of contribution data, including commits and pull requests.
- Costs: Tests accurate cost calculation for managing API rate limits.
- Profiles: Ensures comprehensive fetching and correct parsing of user profiles.
- Repositories: Validates retrieval of detailed repository information.
- Time Range Contributions: Assesses the accuracy of fetching and aggregating contributions within specified time ranges.
4. Integration Tests:
Integration tests verify the interaction between different components of the system, ensuring that they work together as expected. These tests are crucial for assessing the seamless operation of front-end to back-end interactions and the overall data flow within the application:
- TestClient: Tests the GitHub client's ability to initialize correctly, generate headers, handle retries, execute queries efficiently, and manage paginated responses.
- Authentication Tests: Validates the generation of correct authorization headers and proper handling of personal access tokens.
5. Testing Examples:
Here, we provide specific examples of test cases implemented in our project. You can see how we approach testing for both unit and integration levels, focusing on key functionalities and integration points.
<code> @pytest.fixture def valid_token(): return "valid_token_123" @pytest.fixture def authenticator(valid_token): return PersonalAccessTokenAuthenticator(token=valid_token) @pytest.fixture def github_client(authenticator): return Client(authenticator=authenticator) class TestClient: def test_client_initialization(self, github_client): assert github_client._authenticator is not None, "Authenticator should be set." </code>
These tests collectively ensure that the GitHub Miner operates reliably, providing accurate and timely data from GitHub's APIs. By covering a wide range of scenarios, from successful queries to error handling and rate limiting, the tests ensure that the application can be used confidently in production environments.
Live Demo & Source Code
http://152.7.177.239:5000/auth/login Link] (Please login using your personal GitHub accounts, not NCSU accounts)
Team Members
Atharva Pansare
Sumedh Limburkar
Viraj Sanap
Mengning Li
Mentor: Jialin Cui
References
GitHub REST API documentation - https://docs.github.com/en/rest?apiVersion=2022-11-28