From d3dd1758a7056f7533c80a973f312d0ff680632b Mon Sep 17 00:00:00 2001 From: Mridula Maddukuri Date: Sat, 23 Mar 2024 13:43:45 -0700 Subject: [PATCH 1/6] rm eof line --- .pre-commit-config.yaml | 8 +++++++- boilerplate_poetry_project/multiply.py | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 boilerplate_poetry_project/multiply.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1ce2a8a..7e6d537 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,4 +15,10 @@ repos: rev: 5.13.2 hooks: - id: isort - name: isort (python) \ No newline at end of file + name: isort (python) + +- repo: https://github.com/pre-commit/mirrors-mypy + rev: 'v0.910' # Use the sha / tag you want to point at + hooks: + - id: mypy + diff --git a/boilerplate_poetry_project/multiply.py b/boilerplate_poetry_project/multiply.py new file mode 100644 index 0000000..8cd231d --- /dev/null +++ b/boilerplate_poetry_project/multiply.py @@ -0,0 +1,20 @@ +def multiply(x: int, y: int) -> int: + """Multiply two integers. + + Parameters: + - x (int): The first integer to multiply. + - y (int): The second integer to multiply. + + Returns: + - int: The product of x and y. + + Raises: + - TypeError: If either x or y is not an integer. + + Example: + >>> multiply(2, 3) + 6 + """ + if not isinstance(x, int) or not isinstance(y, int): + raise TypeError("Both x and y must be integers.") + return x * y From 1322027be4c15db6a0eedcb4aa9a2f8806f3042b Mon Sep 17 00:00:00 2001 From: Mridula Maddukuri Date: Sat, 23 Mar 2024 13:44:47 -0700 Subject: [PATCH 2/6] + mypy for static type checking --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 0dda060..cd4cd5f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,6 +16,7 @@ isort = "^5.13.2" ruff = "^0.3.4" pytest = "^8.1.1" hypothesis = "^6.99.12" +mypy = "^1.9.0" [build-system] requires = ["poetry-core"] From 2b7dcf0da4f434fd4ad4b2d9d60f69dde25675fb Mon Sep 17 00:00:00 2001 From: Mridula Maddukuri Date: Sat, 23 Mar 2024 13:57:23 -0700 Subject: [PATCH 3/6] isort --- tests/test_multiply.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 tests/test_multiply.py diff --git a/tests/test_multiply.py b/tests/test_multiply.py new file mode 100644 index 0000000..0f0d00e --- /dev/null +++ b/tests/test_multiply.py @@ -0,0 +1,26 @@ +import hypothesis.strategies as st +import pytest +from hypothesis import given + +from boilerplate_poetry_project.multiply import multiply + + +def test_multiply_success(): + """Test that multiplying two integers returns the correct product. + # basic functionality""" + assert multiply(2, 3) == 6 + assert multiply(-1, -1) == 1 + assert multiply(0, 0) == 0 + + +@pytest.mark.parametrize("x, y", [("a", 2), (2, "b"), ("a", "b"), (1.5, 2), (2, 1.5)]) +def test_multiply_raises_type_error_on_invalid_input(x, y): + """Test that a TypeError is raised when non-integers are provided.""" + with pytest.raises(TypeError): + multiply(x, y) + + +@given(x=st.integers(), y=st.integers()) +def test_multiply_with_hypothesis(x, y): + """Test that multiplying two integers returns the correct product using Hypothesis.""" + assert multiply(x, y) == x * y From b28b1c6fc8c6768432900d3c13e38a16a0da307c Mon Sep 17 00:00:00 2001 From: Mridula Maddukuri Date: Sat, 23 Mar 2024 14:00:53 -0700 Subject: [PATCH 4/6] ruff fmt --- boilerplate_poetry_project/multiply.py | 4 ++-- tests/test_multiply.py | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/boilerplate_poetry_project/multiply.py b/boilerplate_poetry_project/multiply.py index 8cd231d..456c886 100644 --- a/boilerplate_poetry_project/multiply.py +++ b/boilerplate_poetry_project/multiply.py @@ -1,4 +1,4 @@ -def multiply(x: int, y: int) -> int: +def multiply_int(x: int, y: int) -> int: """Multiply two integers. Parameters: @@ -12,7 +12,7 @@ def multiply(x: int, y: int) -> int: - TypeError: If either x or y is not an integer. Example: - >>> multiply(2, 3) + >>> multiply_int(2, 3) 6 """ if not isinstance(x, int) or not isinstance(y, int): diff --git a/tests/test_multiply.py b/tests/test_multiply.py index 0f0d00e..a3f73ba 100644 --- a/tests/test_multiply.py +++ b/tests/test_multiply.py @@ -2,25 +2,25 @@ import pytest from hypothesis import given -from boilerplate_poetry_project.multiply import multiply +from boilerplate_poetry_project.multiply import multiply_int -def test_multiply_success(): +def test_multiply_int_success(): """Test that multiplying two integers returns the correct product. # basic functionality""" - assert multiply(2, 3) == 6 - assert multiply(-1, -1) == 1 - assert multiply(0, 0) == 0 + assert multiply_int(2, 3) == 6 + assert multiply_int(-1, -1) == 1 + assert multiply_int(0, 0) == 0 @pytest.mark.parametrize("x, y", [("a", 2), (2, "b"), ("a", "b"), (1.5, 2), (2, 1.5)]) -def test_multiply_raises_type_error_on_invalid_input(x, y): +def test_multiply_int_raises_type_error_on_invalid_input(x, y): """Test that a TypeError is raised when non-integers are provided.""" with pytest.raises(TypeError): - multiply(x, y) + multiply_int(x, y) @given(x=st.integers(), y=st.integers()) -def test_multiply_with_hypothesis(x, y): +def test_multiply_int_with_hypothesis(x, y): """Test that multiplying two integers returns the correct product using Hypothesis.""" - assert multiply(x, y) == x * y + assert multiply_int(x, y) == x * y From b380727ba4e75cc60ec89a5bb231a3515fd948e0 Mon Sep 17 00:00:00 2001 From: Mridula Maddukuri Date: Sat, 23 Mar 2024 14:03:22 -0700 Subject: [PATCH 5/6] add coverage --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index cd4cd5f..51aad87 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,6 +17,7 @@ ruff = "^0.3.4" pytest = "^8.1.1" hypothesis = "^6.99.12" mypy = "^1.9.0" +pytest-cov = "^4.1.0" [build-system] requires = ["poetry-core"] From 5374b52ad3d317232ad64879c17fe0a6573eb942 Mon Sep 17 00:00:00 2001 From: Mridula Maddukuri Date: Sat, 23 Mar 2024 14:09:10 -0700 Subject: [PATCH 6/6] added testing instructions --- README.md | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e3bf219..a0dc9b5 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Efficiently jumpstart your Python projects with boilerplate-poetry-project. Try 1. **Streamline Project Setup:** This repository serves as a boilerplate to efficiently set up your Python project using Poetry for dependency management. 2. **Private Package Publishing:** Documents the process of publishing code as a Python package within a private repository (instructions not included but can be found in the Poetry documentation). -# Getting Started +## Getting Started This project leverages `pyenv` and `poetry` for streamlined environment management. Make sure you have them installed before proceeding. @@ -109,3 +109,51 @@ If you initialize a Poetry project within an existing folder using `poetry init` * Use lowercase letters and underscores (`_`) only (no hyphens or other special characters). * The naming convention should match your project name. For example, if your Poetry project name is `my-project`, the enclosing folder should be named `my_project`. * Using underscores in folder names aligns with how Python expects modules to be structured for import. + + +## Project Dependencies + +This project uses several dependencies managed by Poetry to streamline development, testing, and project management. Below is a list of key dependencies and a brief description of their purpose: + +- **pyenv**: A tool that allows for easy installation and management of multiple Python versions. It's used to set a specific Python version for our project to ensure consistency across development environments. + +- **Poetry**: A dependency management and packaging tool in Python. It's used to declare project libraries, manage their versions, and set up the project's virtual environment. + +- **pytest**: A framework that makes it easy to write simple tests, yet scales to support complex functional testing. It's used for writing and running our project's tests. + +- **pytest-cov**: A plugin for pytest that provides test coverage reporting for our tests. It's useful for identifying parts of the codebase that may not be adequately tested. + +- **Hypothesis**: A library for property-based testing. With Hypothesis, you can write tests that are parameterized according to a source of examples. It's used to generate test cases that might not have been manually considered. + +- **mypy**: An optional static type checker for Python. Mypy checks that the type hints in the codebase are being followed correctly, helping to catch type-related errors before runtime. + +- **pre-commit**: A framework for managing and maintaining multi-language pre-commit hooks. It's used to run checks on the code before committing, ensuring code quality and style consistency. + +- **isort**: A Python utility/library to sort imports alphabetically and automatically separate them into sections. It ensures that import statements are clean and consistently formatted. + +- **ruff**: An extremely fast Python linter. It's used to catch syntax errors and stylistic issues before they make it into the codebase. + + +## Running Tests and Checking Test Coverage + +Ensuring that your code is well-tested is crucial for maintaining high-quality software. This project uses `pytest` for testing and `pytest-cov` to check test coverage. Here's how you can run tests and generate coverage reports. + +### Running Tests + +To run all tests in the project, navigate to the project's root directory and use the following command: + +```bash +poetry run pytest +``` + +This command runs all tests in the project, ensuring that all tests pass. + +### Checking Test Coverage + +To generate a coverage report, use the following command: + +```bash +poetry run pytest --cov +``` + +This command runs all tests in the project and generates a coverage report, showing which parts of the codebase are covered by tests.