튜토리얼: GitLab Duo를 사용하여 Python 쇼핑 애플리케이션의 오류 수정하기
이 튜토리얼은 시리즈의 두 번째 파트입니다. 첫 번째 튜토리얼을 따라 코드가 완벽하게 작동하는 경우, 라우트에서 오류 처리를 제거하여 일반적인 오류를 도입하세요. 시작하기 위해 Chat을 사용하여 웹 애플리케이션에 대한 포괄적인 테스트 케이스를 생성합니다.
이 튜토리얼은 시리즈의 두 번째 파트입니다. 첫 번째 튜토리얼에서는 GitLab Duo를 사용하여 Python으로 쇼핑 애플리케이션을 만들었습니다.
첫 번째 튜토리얼을 따라 코드가 완벽하게 작동하는 경우, 라우트에서 오류 처리를 제거하여 일반적인 오류를 도입하세요. 예를 들어, try 및 catch 블록과 입력 유효성 검사를 제거합니다.
그런 다음 이 튜토리얼을 따라 GitLab Duo의 도움으로 다시 추가합니다.
이 튜토리얼에서는:
- 포괄적인 테스트 케이스를 작성하고, 테스트를 실행하고, 수정해야 할 문제를 식별합니다.
- 데이터베이스 오류 처리 및 연결 관리를 개선합니다.
- 데이터 유효성 검사를 구현합니다.
- 라우트에 강력한 오류 처리를 추가합니다.
- Flask 애플리케이션 구성을 개선합니다.
- 애플리케이션이 올바르게 작동하는지 확인합니다.
테스트 케이스 작성#
시작하기 위해 Chat을 사용하여 웹 애플리케이션에 대한 포괄적인 테스트 케이스를 생성합니다.
잘 작성된 포괄적인 테스트 케이스:
- 코드가 작동하지 않는 위치를 체계적으로 식별합니다.
- 사용자가 표준 조건과 오류 조건 모두에서 코드의 각 부분이 어떻게 작동해야 하는지 정확히 생각하도록 도와줍니다.
- 수정이 필요한 문제의 우선순위 목록을 만듭니다.
- 사용자가 수정이 작동하는지 즉시 검증할 수 있게 합니다.
테스트 케이스를 작성하려면:
-
IDE에서 Chat을 열고 다음을 입력합니다:
I need to write comprehensive tests for a Flask API for a bookstore inventory. Here's the current minimal test file: import pytest def test_dummy(): """A dummy test that always passes.""" assert True Can you help me write proper tests for the application? The API has routes for: - GET /books - Get all books - GET /books/<id> - Get a specific book - POST /books - Add a new book - PUT /books/<id> - Update a book - DELETE /books/<id> - Delete a book I want to test both successful operations and error handling. -
Chat의 응답을 검토합니다. 각 라우트에 대한 설정 코드, 픽스처 정의 및 테스트 함수를 포함하는 포괄적인 테스트 계획을 받아야 합니다.
-
Chat의 응답을 검토한 후, 후속 질문을 해보세요:
-
테스트 픽스처 설계에 대해 더 잘 이해하려고 해보세요:
Can you explain why you're using these specific fixtures? What's the benefit of separating the app fixture from the client fixture? -
Chat에 특정 오류 조건을 테스트하는 방법을 이해하는 데 도움을 요청하세요:
I'm particularly concerned about error handling for the POST and PUT routes. Can you enhance the tests to include more edge cases like invalid data types and missing required fields? -
Flask 테스팅에 대한 더 구체적인 지침을 얻으려면
/help명령을 사용하세요:/help Flask testing with pytest -
테스트를 더 빠르게 실행하는 방법을 Chat에 제안해달라고 요청하세요:
These tests seem comprehensive but might be slow when running the full suite. Are there any optimizations you'd suggest for the test setup?
-
-
필요에 따라 테스트 계획을 수정합니다. 계획에 만족하면 Chat에 테스트 파일의 완전한 구현을 요청합니다:
Based on the test plan, provide a complete implementation of the test_shop.py file that includes: 1. Fixtures for setting up a test client and database 2. Tests for each endpoint with both successful and error cases 3. Proper cleanup after tests -
제안된 구현을
tests/test_shop.py파일에 복사합니다. 테스트 계획을 어떻게 수정했느냐에 따라, 구현은 다음과 유사하게 보여야 합니다:import pytest import json from app import create_app from app.database import initialize_database, get_db_connection @pytest.fixture def app(): """Create and configure a Flask app for testing.""" app = create_app({"TESTING": True, "DATABASE": "test_bookstore.db"}) # Initialize the test database with app.app_context(): initialize_database() yield app # Clean up the test database import os if os.path.exists("test_bookstore.db"): os.remove("test_bookstore.db") @pytest.fixture def client(app): """A test client for the app.""" return app.test_client() @pytest.fixture def init_database(app): """Initialize the database with test data.""" conn = get_db_connection() cursor = conn.cursor() # Add test books cursor.execute( "INSERT INTO articles (name, price, quantity) VALUES (?, ?, ?)", ("Test Book 1", 10.99, 5) ) cursor.execute( "INSERT INTO articles (name, price, quantity) VALUES (?, ?, ?)", ("Test Book 2", 15.99, 10) ) conn.commit() conn.close() def test_get_all_books(client, init_database): """Test retrieving all books.""" response = client.get('/books') assert response.status_code == 200 data = json.loads(response.data) assert len(data) == 2 assert data[0]['name'] == 'Test Book 1' assert data[1]['name'] == 'Test Book 2' def test_get_book_by_id(client, init_database): """Test retrieving a specific book by ID.""" # Test successful retrieval response = client.get('/books/1') assert response.status_code == 200 data = json.loads(response.data) assert data['name'] == 'Test Book 1' assert data['price'] == 10.99 # Test book not found response = client.get('/books/999') assert response.status_code == 404 def test_add_book(client): """Test adding a new book.""" new_book = { 'name': 'New Test Book', 'price': 20.99, 'quantity': 15 } response = client.post('/books', data=json.dumps(new_book), content_type='application/json') assert response.status_code == 201 data = json.loads(response.data) assert data['name'] == 'New Test Book' assert data['price'] == 20.99 assert data['quantity'] == 15 assert 'id' in data def test_update_book(client, init_database): """Test updating an existing book.""" update_data = { 'price': 12.99, 'quantity': 8 } # Test successful update response = client.put('/books/1', data=json.dumps(update_data), content_type='application/json') assert response.status_code == 200 data = json.loads(response.data) assert data['name'] == 'Test Book 1' # Name unchanged assert data['price'] == 12.99 # Price updated assert data['quantity'] == 8 # Quantity updated # Test update for non-existent book response = client.put('/books/999', data=json.dumps(update_data), content_type='application/json') assert response.status_code == 404 def test_delete_book(client, init_database): """Test deleting a book.""" # Test successful deletion response = client.delete('/books/1') assert response.status_code == 200 # Verify book was deleted response = client.get('/books/1') assert response.status_code == 404 # Test deletion of non-existent book response = client.delete('/books/999') assert response.status_code == 404 # This might fail with current implementation
Python 웹 애플리케이션에 대한 포괄적인 테스트 케이스를 만들었습니다.
다음으로 테스트를 실행하여 애플리케이션의 문제를 식별합니다.
테스트를 실행하여 애플리케이션 문제 식별#
이전 섹션에서 생성한 테스트를 실행하여 애플리케이션의 문제를 식별합니다:
pytest -v tests/test_shop.py
실패한 테스트를 검토하여 수정해야 할 문제를 식별합니다.
실패한 테스트 결과는 다음과 유사합니다.
test_delete_book - 실패#
이 테스트는 책을 삭제하려고 시도하고, 그런 다음 존재하지 않는 책(ID 999)을 삭제하려고 시도합니다. 테스트는 다음 동작을 예상합니다:
- 성공적인 삭제는
200상태 코드를 반환합니다. - 존재하지 않는 책을 삭제하려고 하면
404상태 코드를 반환합니다.
이 테스트가 실패하는 이유:
-
app/database.py의delete_article함수가 어떤 상태도 반환하지 않습니다. -
delete_book라우트가:- 삭제 전에 책이 존재하는지 확인하지 않습니다.
- 존재하지 않는 책의 경우를 처리하지 않아 존재하지 않는 책도
200상태 코드를 반환합니다.
test_update_book - 부분 실패#
이 테스트는 기존 책을 업데이트하고 존재하지 않는 책을 업데이트하려고 합니다. 존재하지 않는 책 부분은 통과할 수 있지만 문제가 있습니다:
database.py의update_article함수가 상태를 반환하지 않습니다.- 입력 데이터에 대한 유효성 검사가 발생하지 않습니다.
- 오류 처리가 없습니다.
test_add_book - 잠재적 실패#
이 테스트는 새 책을 추가하고 응답에 상태 코드 201이 있는지 확인합니다. 이 테스트가 실패할 수 있는 이유:
add_book라우트에 입력 유효성 검사가 없습니다.- 데이터가 누락되거나 유효하지 않은 경우 오류 처리가 없습니다.
Article클래스가 음수 가격과 같은 입력을 유효성 검사하지 않습니다.
테스트 클라이언트 설정 - 잠재적 실패#
테스트 픽스처가 실패할 수 있는 이유:
- 애플리케이션이 테스트 구성을 제대로 처리하지 않습니다.
create_app함수가 제공된 테스트 구성을 사용하지 않습니다.- 데이터베이스 경로가 하드코딩되어 테스트 데이터베이스를 사용하기 어렵습니다.
모든 테스트에 영향을 미치는 일반적인 문제#
코드베이스의 여러 문제가 모든 테스트에 영향을 미칩니다:
- 데이터베이스 작업에 오류 처리가 없습니다.
- 애플리케이션 전체에 입력 유효성 검사가 없습니다.
- 하드코딩된 구성 값.
- 중요한 환경 변수가 없습니다.
- 데이터베이스 함수에 연결 관리가 없습니다.
애플리케이션을 견고하고 테스트 가능하게 만들려면 이러한 문제를 해결해야 합니다.
실패한 테스트 식별 후 다음 단계#
어떤 테스트가 실패하는지 확인한 후, Chat과 Code Suggestions을 사용하여 다음을 통해 체계적으로 이러한 문제를 해결합니다:
- 데이터베이스 오류 처리 및 연결 관리 개선.
- Article 클래스에서 데이터 유효성 검사 구현.
- 라우트 함수에 적절한 오류 처리 추가.
- 애플리케이션 구성 개선.
- 수정 사항 테스트 및 검증.
데이터베이스 오류 처리 및 연결 관리 개선#
이제 Code Suggestions(특히 코드 생성)을 사용하여 데이터베이스 오류 처리 및 연결 관리를 개선합니다:
-
IDE에서
app/database.py파일을 엽니다. -
먼저 하드코딩된 데이터베이스 경로를 수정합니다.
DATABASE_PATH가 정의된 줄에 커서를 위치시키고 다음을 입력합니다:# Replace the hard coded database path with an environment variable for database path with a fallback DATABASE_PATH = 'bookstore.db' -
필요에 따라 생성된 코드를 검토하고 조정합니다. 다음과 유사하게 보여야 합니다:
import os from dotenv import load_dotenv load_dotenv() # Use environment variable for database path with a fallback DATABASE_PATH = os.getenv('DATABASE_PATH', 'bookstore.db') -
다음으로, 오류 처리를 통해
get_db_connection()함수를 개선합니다. 함수 끝에 커서를 위치시키고 다음을 입력합니다:# Add in missing error handling and connection management. -
생성된 코드를 검토하고 필요에 따라 조정합니다. 다음과 유사하게 보여야 합니다:
def get_db_connection(): """ Get a database connection. Returns: sqlite3.Connection: Database connection object Raises: sqlite3.Error: If connection to database fails """ try: conn = sqlite3.connect(DATABASE_PATH) conn.row_factory = sqlite3.Row return conn except sqlite3.Error as e: # Log the error print(f"Database connection error: {e}") raise -
레코드가 실제로 삭제되었는지 확인하고 상태를 반환하도록
delete_article함수를 개선합니다:# Modify the `delete_article` to return a boolean indicating success if article # was deleted, or failure if article was not found -
생성된 코드를 검토하고 필요에 따라 조정합니다. 다음과 유사하게 보여야 합니다:
def delete_article(article_id): """ Delete an article from the database. Args: article_id (int): ID of the article to delete Returns: bool: True if article was deleted, False if article was not found """ try: conn = get_db_connection() cursor = conn.cursor() cursor.execute("DELETE FROM articles WHERE id = ?", (article_id,)) deleted = cursor.rowcount > 0 conn.commit() conn.close() return deleted except sqlite3.Error as e: print(f"Error deleting article: {e}") return False -
마지막으로, 성공을 나타내는 상태를 반환하도록
update_article함수를 개선합니다:# Modify the update_article function to return a boolean indicating success if article # was deleted, or failure if article was not found -
생성된 코드를 검토하고 필요에 따라 조정합니다. 다음과 유사하게 보여야 합니다:
def update_article(article): """ Update an existing article in the database. Args: article (Article): Article object with updated values Returns: bool: True if article was updated, False if article was not found """ try: conn = get_db_connection() cursor = conn.cursor() cursor.execute( "UPDATE articles SET name = ?, price = ?, quantity = ? WHERE id = ?", (article.name, article.price, article.quantity, article.id) ) updated = cursor.rowcount > 0 conn.commit() conn.close() return updated except sqlite3.Error as e: print(f"Error updating article: {e}") return False
잘 하셨습니다. Code Suggestions를 사용하여 데이터베이스 오류 처리 및 연결 관리를 개선했습니다. 다음으로 Chat을 사용하여 Article 클래스에 데이터 유효성 검사를 구현합니다.
데이터 유효성 검사 구현#
이제 Chat을 사용하여 Article 클래스에 대한 유효성 검사 규칙을 구현하는 데 도움을 받습니다:
-
IDE에서 Chat을 열고 다음을 입력합니다:
How can I implement data validation rules for the Article class? I need to validate name as a non-empty string, price as a positive integer, quantity as a non-negative integer, and handle any validation errors. -
응답을 검토합니다. 응답을 개선하기 위해 후속 질문을 해보세요:
-
Chat에 유효성 검사 구현의 특정 부분을 설명해달라고 요청합니다:
Can you explain how the ValidationError class works in this implementation? Why is it defined as an inner class rather than separately? -
유효성 검사에 대한 더 효율적인 접근 방식을 제안해달라고 Chat에 요청합니다:
The validation logic in the constructor feels verbose. Is there a more efficient way to handle the validation, perhaps using Python decorators or a validation library? -
Chat에 유효성 검사 코드를 리팩토링해달라고 요청합니다:
Can you refactor the validation code to make it more maintainable? Perhaps extract the validation logic into separate methods?
-
-
리팩토링된 코드 응답을 검토하고 개선된 Article 클래스를 구현합니다. 다음과 유사해야 합니다:
class Article: """Article class for a bookstore inventory system.""" class ValidationError(Exception): """Exception raised for validation errors in article attributes.""" pass def __init__(self, name, price, quantity, article_id=None): """ Initialize an article. Args: name (str): The name/title of the book price (float): The price of the book quantity (int): The quantity in stock article_id (int, optional): The unique identifier for the article Raises: ValidationError: If any of the inputs fail validation """ self.id = article_id # Validate name if not name or not isinstance(name, str) or len(name.strip()) == 0: raise self.ValidationError("Article name must be a non-empty string") self.name = name.strip() # Validate price try: price_float = float(price) if price_float <= 0: raise self.ValidationError("Price must be a positive number") self.price = price_float except (ValueError, TypeError): raise self.ValidationError("Price must be a valid number") # Validate quantity try: quantity_int = int(quantity) if quantity_int < 0: raise self.ValidationError("Quantity cannot be negative") self.quantity = quantity_int except (ValueError, TypeError): raise self.ValidationError("Quantity must be a valid integer") def to_dict(self): """ Convert the article to a dictionary. Returns: dict: Dictionary representation of the article """ return { "id": self.id, "name": self.name, "price": self.price, "quantity": self.quantity } @classmethod def from_dict(cls, data): """ Create an article from a dictionary. Args: data (dict): Dictionary with article data Returns: Article: New article instance Raises: ValidationError: If the dictionary is missing required fields or data fails validation KeyError: If a required key is missing from the dictionary """ # Validate required fields required_fields = ["name", "price", "quantity"] for field in required_fields: if field not in data: raise cls.ValidationError(f"Missing required field: {field}") article_id = data.get("id") # Create and return new article with validation return cls( name=data["name"], price=data["price"], quantity=data["quantity"], article_id=article_id ) -
선택 사항. 추가적인 Python 데이터 유효성 검사 기법에 대해 Chat에 질문하세요.
필요한 경우
/explain슬래시 명령을 사용하여 추가 기법을 이해합니다.
GitLab Duo Chat을 사용하여 Article 클래스에 데이터 유효성 검사를 구현했습니다.
다음으로 Code Suggestions를 사용하여 라우트의 오류 처리를 개선합니다.
라우트에서 오류 처리 구현#
이제 Code Suggestions를 사용하여 라우트의 오류 처리를 개선합니다:
-
IDE에서
app/routes/shop.py파일을 엽니다. -
먼저 GET 라우트에 더 나은 오류 처리를 추가합니다.
get_all_books함수의 시작 부분에 커서를 위치시키고 다음을 입력합니다:# Implement error handling in the get_all_books function -
생성된 코드를 검토하고 필요에 따라 조정합니다. 다음과 유사하게 보여야 합니다:
@shop_bp.route('', methods=['GET']) def get_all_books(): """Get all books from the inventory.""" try: books = database.get_all_articles() return jsonify([book.to_dict() for book in books]) except Exception as e: # Log the error print(f"Error retrieving books: {e}") return jsonify({"error": "Failed to retrieve books", "details": str(e)}), 500 -
다음으로, Code Suggestions를 사용하여 적절한 유효성 검사 및 오류 처리로
add_book함수를 업데이트합니다.add_book함수의 시작 부분에 다음을 입력합니다:# Add validation for input data in the `add_book` route, implement proper # error handling, and enhance the `Article` class with validation for name, # price, and quantity -
생성된 코드를 검토하고 필요에 따라 조정합니다. 다음과 유사하게 보여야 합니다:
@shop_bp.route('', methods=['POST']) def add_book(): """Add a new book to the inventory.""" try: # Check if request contains JSON data if not request.is_json: return jsonify({"error": "Request must be JSON"}), 400 data = request.get_json() # Validate required fields required_fields = ["name", "price", "quantity"] for field in required_fields: if field not in data: return jsonify({"error": f"Missing required field: {field}"}), 400 # Create new book with validation try: new_book = Article( name=data['name'], price=data['price'], quantity=data['quantity'] ) except Article.ValidationError as e: return jsonify({"error": "Validation error", "details": str(e)}), 400 # Add to database book_id = database.add_article(new_book) if book_id: created_book = database.get_article_by_id(book_id) return jsonify(created_book.to_dict()), 201 else: return jsonify({"error": "Failed to add book to database"}), 500 except Exception as e: # Log the error print(f"Error adding book: {e}") return jsonify({"error": "Internal server error", "details": str(e)}), 500 -
책이 존재하는지 확인하고 오류를 올바르게 처리하도록
delete_book함수를 업데이트합니다.delete_book함수의 시작 부분에 다음을 입력합니다:# Update the `delete_book` route to check if the book exists before deletion, # and return a 404 status code if the book does not exist -
생성된 코드를 확인하고 필요에 따라 조정합니다. 다음과 유사하게 보여야 합니다:
@shop_bp.route('/<int:book_id>', methods=['DELETE']) def delete_book(book_id): """Delete a book from the inventory.""" try: # Check if book exists before deletion existing_book = database.get_article_by_id(book_id) if not existing_book: return jsonify({"error": "Book not found"}), 404 # Delete the book success = database.delete_article(book_id) if success: return jsonify({"message": "Book deleted successfully"}), 200 else: return jsonify({"error": "Failed to delete book"}), 500 except Exception as e: # Log the error print(f"Error deleting book: {e}") return jsonify({"error": "Internal server error", "details": str(e)}), 500 -
마지막으로, Code Suggestions를 사용하여
update_book함수의 오류 처리를 개선합니다.update_book함수의 시작 부분에 다음을 입력합니다:# Update the `update_book` route to check if the book exists before updating, # update the book with price and quantity validation, save the updated book, # and return a 500 status code if the book does not exist -
생성된 코드를 확인하고 필요에 따라 조정합니다. 다음과 유사하게 보여야 합니다:
@shop_bp.route('/<int:book_id>', methods=['PUT']) def update_book(book_id): """Update an existing book.""" try: # Check if request contains JSON data if not request.is_json: return jsonify({"error": "Request must be JSON"}), 400 data = request.get_json() # Check if book exists existing_book = database.get_article_by_id(book_id) if not existing_book: return jsonify({"error": "Book not found"}), 404 # Update book properties with validation try: if 'name' in data: existing_book.name = data['name'] if 'price' in data: existing_book.price = float(data['price']) if existing_book.price <= 0: return jsonify({"error": "Price must be a positive number"}), 400 if 'quantity' in data: existing_book.quantity = int(data['quantity']) if existing_book.quantity < 0: return jsonify({"error": "Quantity cannot be negative"}), 400 except (ValueError, TypeError) as e: return jsonify({"error": "Invalid data format", "details": str(e)}), 400 except Article.ValidationError as e: return jsonify({"error": "Validation error", "details": str(e)}), 400 # Save updated book success = database.update_article(existing_book) if success: updated_book = database.get_article_by_id(book_id) return jsonify(updated_book.to_dict()), 200 else: return jsonify({"error": "Failed to update book"}), 500 except Exception as e: # Log the error print(f"Error updating book: {e}") return jsonify({"error": "Internal server error", "details": str(e)}), 500
잘 하셨습니다. 라우트의 오류 처리를 성공적으로 개선했습니다.
다음으로 Chat을 사용하여 Flask 애플리케이션 구성을 개선합니다.
Flask 애플리케이션 구성 개선#
마지막 개선 사항으로, Chat을 사용하여 Flask 애플리케이션 구성을 개선합니다.
-
IDE에서
app/__init__.py파일을 엽니다. -
IDE에서 Chat을 열고 다음을 입력합니다:
I need to improve this Flask application initialization code, specifically the security configuration and environment variable handling defined in the `create_app` function. -
응답을 검토합니다.
create_app함수를 개선하기 위한 후속 질문을 해보세요:-
특정 보안 개선을 요청합니다:
What are the best practices for handling secret keys in a Flask application? How should I generate and manage them differently between development and production environments? -
Flask 애플리케이션 구조 모범 사례에 대해 질문합니다:
Are there any architectural improvements you'd suggest for this Flask application beyond configuration handling? How would professional Flask applications structure this differently? -
구성 선택의 함의를 설명해달라고 요청합니다:
Can you explain the security implications of these configuration choices? What other Flask configurationsettings should I be aware of for a secure deployment?
-
-
응답을 기반으로,
create_app함수를 개선합니다. 후속 질문에 따라, 함수는 다음과 유사하게 보여야 합니다:from flask import Flask def create_app(test_config=None): """ Application factory for creating the Flask app. Args: test_config (dict, optional): Test configuration to override default config Returns: Flask: Configured Flask application """ # Create and configure the app app = Flask(__name__) # Set default configuration app.config.from_mapping( SECRET_KEY='dev', # Hard coded secret key ) # Missing configuration from environment variables # Missing test config handling # Initialize database from app import database database.initialize_database() # Register blueprints from app.routes.shop import shop_bp app.register_blueprint(shop_bp) # Add a simple index route @app.route('/') def index(): return { "message": "Welcome to the Bookstore Inventory API" } return app -
다음으로, 환경 변수를 사용하여 테스트 구성을 올바르게 처리하도록
create_app을 업데이트합니다. Chat에 다음을 입력합니다:How can I update create_app to properly handle test configuration and use environment variables -
생성된 코드를 검토하고 필요에 따라 조정합니다. 다음과 유사하게 보여야 합니다:
import os from flask import Flask from dotenv import load_dotenv load_dotenv() # Load environment variables from .env file def create_app(test_config=None): """ Application factory for creating the Flask app. Args: test_config (dict, optional): Test configuration to override default config Returns: Flask: Configured Flask application """ # Create and configure the app app = Flask(__name__) # Set default configuration app.config.from_mapping( SECRET_KEY=os.getenv('SECRET_KEY', 'dev'), DATABASE_PATH=os.getenv('DATABASE_PATH', 'bookstore.db'), DEBUG=os.getenv('FLASK_ENV') == 'development', ) # Override config with test config if provided if test_config: app.config.update(test_config) # Ensure instance folder exists os.makedirs(app.instance_path, exist_ok=True) # Initialize database from app import database database.initialize_database() # Register blueprints from app.routes.shop import shop_bp app.register_blueprint(shop_bp) # Add a simple index route @app.route('/') def index(): return { "message": "Welcome to the Bookstore Inventory API", "version": "1.0", "endpoints": { "GET /books": "Get all books", "GET /books/<id>": "Get a specific book", "POST /books": "Add a new book", "PUT /books/<id>": "Update a book", "DELETE /books/<id>": "Delete a book" } } # Add error handlers @app.errorhandler(404) def not_found(e): return {"error": "Not found"}, 404 @app.errorhandler(500) def server_error(e): return {"error": "Internal server error"}, 500 return app -
마지막으로, 적절한 구성으로 개선된
.env파일을 만듭니다:FLASK_APP=app FLASK_ENV=development SECRET_KEY=your_secure_secret_key_for_development DATABASE_PATH=bookstore.db -
선택 사항. Chat에 환경 변수에 대한 보안 모범 사례를 요청하여 구성 처리를 더욱 개선할 수 있습니다:
/security What are the best practices for handling environment variables and sensitive configuration in a Flask application?제공된 지침을 사용하여 구성 처리를 더욱 개선합니다.
테스트를 다시 실행하고 애플리케이션이 작동하는지 확인#
문제를 수정하고 개선 사항을 구현했으므로, 모든 것이 올바르게 작동하는지 확인합니다:
-
모든 테스트가 통과하는지 확인하기 위해 테스트를 다시 실행합니다:
pytest -v tests/test_shop.py -
Flask 애플리케이션을 시작합니다:
flask run -
유효하고 유효하지 않은 입력 모두로 API 엔드포인트를 테스트합니다. 이를 위해 Postman 또는 curl과 같은 API 개발 도구를 다음 엔드포인트에 사용합니다.
- 유효한 요청으로
GET /books. - 유효한 ID로
GET /books/1. - 유효하지 않은 ID로
GET /books/999. - 유효하고 유효하지 않은(예: 누락된 필드, 음수 가격) 데이터로
POST /books. - 유효하고 유효하지 않은 데이터로
PUT /books/1. DELETE /books/1.- 존재하지 않는 ID로
DELETE /books/999.
- 유효한 요청으로
-
모든 오류 케이스에 대해 오류 처리가 올바르게 작동하는지 확인합니다.
-
선택 사항. 오류 처리가 올바르게 작동하는지 확인하는 방법을 Chat에 질문합니다.
요약#
이 튜토리얼에서는 Chat과 Code Suggestions를 사용하여 다음을 수행했습니다:
- 포괄적인 테스트 케이스를 작성하고, 테스트를 실행하고, 수정해야 할 문제를 식별했습니다.
- 데이터베이스 오류 처리 및 연결 관리를 개선했습니다.
- 데이터 유효성 검사를 구현했습니다.
- 라우트에 강력한 오류 처리를 추가했습니다.
- Flask 애플리케이션 구성을 개선했습니다.
- 애플리케이션이 올바르게 작동하는지 확인했습니다.
이러한 개선으로 애플리케이션이 더 안정적이고, 안전하며, 유지 관리하기 쉽게 되었습니다.
