mirror of
https://github.com/octocat/Hello-World.git
synced 2026-06-04 14:17:09 +00:00
Add payment test suite with Jenkins CI/CD integration
This commit is contained in:
parent
141a64342c
commit
a4adc2e219
43
.gitignore
vendored
Normal file
43
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# Python
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
*.so
|
||||
.Python
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# Testing
|
||||
.pytest_cache/
|
||||
.coverage
|
||||
htmlcov/
|
||||
test-results.xml
|
||||
test-report.html
|
||||
coverage.xml
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
94
Jenkinsfile
vendored
Normal file
94
Jenkinsfile
vendored
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
pipeline {
|
||||
agent any
|
||||
|
||||
environment {
|
||||
PYTHON_VERSION = '3.9'
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Checkout') {
|
||||
steps {
|
||||
echo 'Checking out code...'
|
||||
checkout scm
|
||||
}
|
||||
}
|
||||
|
||||
stage('Setup Python Environment') {
|
||||
steps {
|
||||
echo 'Setting up Python environment...'
|
||||
bat '''
|
||||
python --version
|
||||
python -m pip install --upgrade pip
|
||||
'''
|
||||
}
|
||||
}
|
||||
|
||||
stage('Install Dependencies') {
|
||||
steps {
|
||||
echo 'Installing dependencies...'
|
||||
bat '''
|
||||
pip install -r requirements.txt
|
||||
'''
|
||||
}
|
||||
}
|
||||
|
||||
stage('Run Tests') {
|
||||
steps {
|
||||
echo 'Running payment tests...'
|
||||
bat '''
|
||||
pytest tests/ -v --junitxml=test-results.xml --html=test-report.html --self-contained-html
|
||||
'''
|
||||
}
|
||||
}
|
||||
|
||||
stage('Code Coverage') {
|
||||
steps {
|
||||
echo 'Generating code coverage report...'
|
||||
bat '''
|
||||
pytest tests/ --cov=src --cov-report=html --cov-report=xml
|
||||
'''
|
||||
}
|
||||
}
|
||||
|
||||
stage('Publish Results') {
|
||||
steps {
|
||||
echo 'Publishing test results...'
|
||||
junit 'test-results.xml'
|
||||
|
||||
publishHTML(target: [
|
||||
allowMissing: false,
|
||||
alwaysLinkToLastBuild: true,
|
||||
keepAll: true,
|
||||
reportDir: 'htmlcov',
|
||||
reportFiles: 'index.html',
|
||||
reportName: 'Coverage Report'
|
||||
])
|
||||
|
||||
publishHTML(target: [
|
||||
allowMissing: false,
|
||||
alwaysLinkToLastBuild: true,
|
||||
keepAll: true,
|
||||
reportDir: '.',
|
||||
reportFiles: 'test-report.html',
|
||||
reportName: 'Test Report'
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
post {
|
||||
always {
|
||||
echo 'Cleaning up...'
|
||||
cleanWs(patterns: [
|
||||
[pattern: '**/__pycache__', type: 'INCLUDE'],
|
||||
[pattern: '**/*.pyc', type: 'INCLUDE']
|
||||
])
|
||||
}
|
||||
success {
|
||||
echo 'Pipeline completed successfully!'
|
||||
}
|
||||
failure {
|
||||
echo 'Pipeline failed!'
|
||||
}
|
||||
}
|
||||
}
|
||||
56
README
56
README
|
|
@ -1 +1,55 @@
|
|||
Hello World!
|
||||
# Hello World - Payment Test Suite
|
||||
|
||||
This repository contains a dummy payment service with comprehensive test cases designed to run through Jenkins CI/CD pipeline.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Run Tests Locally
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
pytest tests/ -v
|
||||
```
|
||||
|
||||
### View Coverage
|
||||
```bash
|
||||
pytest tests/ --cov=src --cov-report=html
|
||||
```
|
||||
|
||||
## What's Included
|
||||
|
||||
- **Payment Service**: Dummy payment processing module
|
||||
- **21 Test Cases**: Comprehensive test coverage including positive, negative, and edge cases
|
||||
- **Jenkins Pipeline**: Automated CI/CD configuration
|
||||
- **Coverage Reports**: HTML and XML coverage reporting
|
||||
|
||||
## Documentation
|
||||
|
||||
See [SETUP_GUIDE.md](SETUP_GUIDE.md) for complete setup instructions and Jenkins configuration.
|
||||
|
||||
## Test Results
|
||||
|
||||
The test suite includes:
|
||||
- ✅ 4 Positive test cases
|
||||
- ❌ 8 Negative test cases
|
||||
- 🔍 9 Edge case tests
|
||||
|
||||
Total: **21 automated tests**
|
||||
|
||||
## Jenkins Integration
|
||||
|
||||
This project includes a complete Jenkinsfile that:
|
||||
1. Checks out code
|
||||
2. Sets up Python environment
|
||||
3. Installs dependencies
|
||||
4. Runs all tests
|
||||
5. Generates coverage reports
|
||||
6. Publishes results
|
||||
|
||||
## Project Structure
|
||||
```
|
||||
Hello-World/
|
||||
├── src/ # Payment service source code
|
||||
├── tests/ # Test cases
|
||||
├── Jenkinsfile # Jenkins pipeline
|
||||
└── requirements.txt # Dependencies
|
||||
```
|
||||
|
|
|
|||
271
SETUP_GUIDE.md
Normal file
271
SETUP_GUIDE.md
Normal file
|
|
@ -0,0 +1,271 @@
|
|||
# Payment Test Suite - Jenkins Setup Guide
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
Hello-World/
|
||||
├── src/
|
||||
│ ├── __init__.py
|
||||
│ └── payment_service.py # Dummy payment service
|
||||
├── tests/
|
||||
│ ├── __init__.py
|
||||
│ └── test_payment.py # Payment test cases (21 tests)
|
||||
├── Jenkinsfile # Jenkins pipeline configuration
|
||||
├── requirements.txt # Python dependencies
|
||||
├── pytest.ini # Pytest configuration
|
||||
├── .gitignore # Git ignore patterns
|
||||
├── SETUP_GUIDE.md # This file
|
||||
└── README # Original readme
|
||||
|
||||
```
|
||||
|
||||
## Test Cases Included
|
||||
|
||||
The test suite includes **21 comprehensive test cases**:
|
||||
|
||||
### Positive Tests
|
||||
1. ✅ Successful payment processing
|
||||
2. ✅ Multiple payments handling
|
||||
3. ✅ Transaction retrieval
|
||||
4. ✅ Successful refund processing
|
||||
|
||||
### Negative Tests
|
||||
5. ❌ Invalid amount (zero)
|
||||
6. ❌ Invalid amount (negative)
|
||||
7. ❌ Invalid card number (too short)
|
||||
8. ❌ Invalid card number (empty)
|
||||
9. ❌ Invalid CVV (too short)
|
||||
10. ❌ Invalid CVV (empty)
|
||||
11. ❌ Refund non-existent transaction
|
||||
12. ❌ Duplicate refund
|
||||
|
||||
### Edge Cases
|
||||
13. 🔍 Large amount payment
|
||||
14. 🔍 Small amount payment
|
||||
15. 🔍 Get all transactions (empty)
|
||||
16. 🔍 Get non-existent transaction
|
||||
17. 🔍 Card number masking
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Local Setup
|
||||
1. **Python 3.9+** installed
|
||||
2. **Git** installed
|
||||
3. **pip** package manager
|
||||
|
||||
### Jenkins Setup
|
||||
1. **Jenkins** server installed and running
|
||||
2. **Python plugin** for Jenkins
|
||||
3. **HTML Publisher plugin** for Jenkins
|
||||
4. **JUnit plugin** for Jenkins (usually pre-installed)
|
||||
|
||||
## Step-by-Step Procedure
|
||||
|
||||
### Part 1: Local Testing (Optional but Recommended)
|
||||
|
||||
1. **Clone/Navigate to your repository:**
|
||||
```bash
|
||||
cd d:\Hello-World
|
||||
```
|
||||
|
||||
2. **Install dependencies:**
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
3. **Run tests locally:**
|
||||
```bash
|
||||
# Run all tests
|
||||
pytest tests/ -v
|
||||
|
||||
# Run with coverage
|
||||
pytest tests/ --cov=src --cov-report=html
|
||||
|
||||
# Run specific test
|
||||
pytest tests/test_payment.py::TestPaymentService::test_successful_payment -v
|
||||
```
|
||||
|
||||
4. **View coverage report:**
|
||||
```bash
|
||||
# Open htmlcov/index.html in your browser
|
||||
start htmlcov/index.html
|
||||
```
|
||||
|
||||
### Part 2: Jenkins Setup
|
||||
|
||||
#### Option A: Jenkins Pipeline (Recommended)
|
||||
|
||||
1. **Install Required Jenkins Plugins:**
|
||||
- Go to Jenkins → Manage Jenkins → Manage Plugins
|
||||
- Install:
|
||||
- Pipeline
|
||||
- Git plugin
|
||||
- HTML Publisher plugin
|
||||
- JUnit plugin
|
||||
|
||||
2. **Create New Jenkins Job:**
|
||||
- Click "New Item"
|
||||
- Enter job name: `Payment-Test-Suite`
|
||||
- Select "Pipeline"
|
||||
- Click OK
|
||||
|
||||
3. **Configure Pipeline:**
|
||||
- Scroll to "Pipeline" section
|
||||
- Definition: Select "Pipeline script from SCM"
|
||||
- SCM: Select "Git"
|
||||
- Repository URL: Enter your Git repository URL
|
||||
- Branch: `*/main` (or your default branch)
|
||||
- Script Path: `Jenkinsfile`
|
||||
- Click "Save"
|
||||
|
||||
4. **Run the Pipeline:**
|
||||
- Click "Build Now"
|
||||
- Monitor the build in the console output
|
||||
|
||||
#### Option B: Freestyle Project
|
||||
|
||||
1. **Create New Jenkins Job:**
|
||||
- Click "New Item"
|
||||
- Enter job name: `Payment-Test-Suite-Freestyle`
|
||||
- Select "Freestyle project"
|
||||
- Click OK
|
||||
|
||||
2. **Source Code Management:**
|
||||
- Select "Git"
|
||||
- Repository URL: Enter your repository URL
|
||||
- Branch: `*/main`
|
||||
|
||||
3. **Build Steps:**
|
||||
- Add build step → Execute Windows batch command
|
||||
```batch
|
||||
python -m pip install --upgrade pip
|
||||
pip install -r requirements.txt
|
||||
pytest tests/ -v --junitxml=test-results.xml --html=test-report.html --self-contained-html
|
||||
pytest tests/ --cov=src --cov-report=html --cov-report=xml
|
||||
```
|
||||
|
||||
4. **Post-build Actions:**
|
||||
- Add "Publish JUnit test result report"
|
||||
- Test report XMLs: `test-results.xml`
|
||||
- Add "Publish HTML reports"
|
||||
- HTML directory to archive: `htmlcov`
|
||||
- Index page: `index.html`
|
||||
- Report title: `Coverage Report`
|
||||
|
||||
5. **Save and Build:**
|
||||
- Click "Save"
|
||||
- Click "Build Now"
|
||||
|
||||
### Part 3: GitHub/Git Integration
|
||||
|
||||
1. **Push your code to Git:**
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "Add payment test suite and Jenkins pipeline"
|
||||
git push origin main
|
||||
```
|
||||
|
||||
2. **Configure Webhook (Optional - for automatic builds):**
|
||||
- In GitHub: Settings → Webhooks → Add webhook
|
||||
- Payload URL: `http://your-jenkins-url/github-webhook/`
|
||||
- Content type: `application/json`
|
||||
- Select: "Just the push event"
|
||||
- Active: ✓
|
||||
|
||||
3. **In Jenkins Job Configuration:**
|
||||
- Build Triggers → Check "GitHub hook trigger for GITScm polling"
|
||||
|
||||
### Part 4: Viewing Results
|
||||
|
||||
After a successful build, you can view:
|
||||
|
||||
1. **Test Results:**
|
||||
- Click on build number → Test Results
|
||||
- Shows all 21 test cases with pass/fail status
|
||||
|
||||
2. **Coverage Report:**
|
||||
- Click on build number → Coverage Report
|
||||
- Shows code coverage percentage
|
||||
|
||||
3. **HTML Test Report:**
|
||||
- Click on build number → Test Report
|
||||
- Detailed HTML report with test execution details
|
||||
|
||||
4. **Console Output:**
|
||||
- Click on build number → Console Output
|
||||
- View complete build log
|
||||
|
||||
## Jenkins Pipeline Stages
|
||||
|
||||
The Jenkinsfile includes these stages:
|
||||
|
||||
1. **Checkout** - Pulls code from repository
|
||||
2. **Setup Python Environment** - Verifies Python installation
|
||||
3. **Install Dependencies** - Installs required packages
|
||||
4. **Run Tests** - Executes all test cases
|
||||
5. **Code Coverage** - Generates coverage report
|
||||
6. **Publish Results** - Publishes test and coverage reports
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
1. **Python not found:**
|
||||
- Add Python to system PATH
|
||||
- In Jenkins: Manage Jenkins → Global Tool Configuration → Add Python
|
||||
|
||||
2. **Module not found:**
|
||||
- Ensure `requirements.txt` is installed
|
||||
- Check virtual environment activation
|
||||
|
||||
3. **Tests not discovered:**
|
||||
- Verify pytest.ini configuration
|
||||
- Check test file naming (test_*.py)
|
||||
|
||||
4. **HTML reports not showing:**
|
||||
- Install HTML Publisher plugin
|
||||
- Configure Content Security Policy:
|
||||
```
|
||||
Manage Jenkins → Script Console → Run:
|
||||
System.setProperty("hudson.model.DirectoryBrowserSupport.CSP", "")
|
||||
```
|
||||
|
||||
## Running Specific Test Categories
|
||||
|
||||
```bash
|
||||
# Run only successful payment tests
|
||||
pytest tests/test_payment.py -k "successful" -v
|
||||
|
||||
# Run only negative tests
|
||||
pytest tests/test_payment.py -k "invalid" -v
|
||||
|
||||
# Run with markers (if configured)
|
||||
pytest tests/ -m "unit" -v
|
||||
```
|
||||
|
||||
## CI/CD Best Practices
|
||||
|
||||
1. **Run tests on every commit**
|
||||
2. **Maintain >80% code coverage**
|
||||
3. **Review failed tests immediately**
|
||||
4. **Keep test execution time < 5 minutes**
|
||||
5. **Archive test reports for compliance**
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. Add more test cases for edge scenarios
|
||||
2. Integrate with Slack/Email for notifications
|
||||
3. Add performance testing
|
||||
4. Implement test data management
|
||||
5. Add security scanning stages
|
||||
|
||||
## Support
|
||||
|
||||
For issues or questions:
|
||||
- Check Jenkins console output
|
||||
- Review test logs in test-report.html
|
||||
- Verify Python and dependency versions
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** May 2026
|
||||
23
pytest.ini
Normal file
23
pytest.ini
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
[pytest]
|
||||
# Pytest configuration file
|
||||
|
||||
# Test discovery patterns
|
||||
python_files = test_*.py
|
||||
python_classes = Test*
|
||||
python_functions = test_*
|
||||
|
||||
# Test paths
|
||||
testpaths = tests
|
||||
|
||||
# Output options
|
||||
addopts =
|
||||
-v
|
||||
--strict-markers
|
||||
--tb=short
|
||||
--disable-warnings
|
||||
|
||||
# Markers
|
||||
markers =
|
||||
slow: marks tests as slow
|
||||
integration: marks tests as integration tests
|
||||
unit: marks tests as unit tests
|
||||
7
requirements.txt
Normal file
7
requirements.txt
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# Testing Dependencies
|
||||
pytest==7.4.3
|
||||
pytest-html==4.1.1
|
||||
pytest-cov==4.1.0
|
||||
|
||||
# Code Quality
|
||||
flake8==6.1.0
|
||||
1
src/__init__.py
Normal file
1
src/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
|||
# Payment Service Package
|
||||
117
src/payment_service.py
Normal file
117
src/payment_service.py
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
"""
|
||||
Dummy Payment Service for Testing
|
||||
"""
|
||||
|
||||
class PaymentService:
|
||||
"""Simple payment service for demonstration"""
|
||||
|
||||
def __init__(self):
|
||||
self.transactions = []
|
||||
|
||||
def process_payment(self, amount, card_number, cvv):
|
||||
"""
|
||||
Process a payment transaction
|
||||
|
||||
Args:
|
||||
amount (float): Payment amount
|
||||
card_number (str): Card number
|
||||
cvv (str): CVV code
|
||||
|
||||
Returns:
|
||||
dict: Transaction result
|
||||
"""
|
||||
if amount <= 0:
|
||||
return {
|
||||
"status": "failed",
|
||||
"message": "Invalid amount",
|
||||
"transaction_id": None
|
||||
}
|
||||
|
||||
if not card_number or len(card_number) != 16:
|
||||
return {
|
||||
"status": "failed",
|
||||
"message": "Invalid card number",
|
||||
"transaction_id": None
|
||||
}
|
||||
|
||||
if not cvv or len(cvv) != 3:
|
||||
return {
|
||||
"status": "failed",
|
||||
"message": "Invalid CVV",
|
||||
"transaction_id": None
|
||||
}
|
||||
|
||||
transaction_id = f"TXN{len(self.transactions) + 1:06d}"
|
||||
transaction = {
|
||||
"transaction_id": transaction_id,
|
||||
"amount": amount,
|
||||
"card_number": f"****{card_number[-4:]}",
|
||||
"status": "success"
|
||||
}
|
||||
|
||||
self.transactions.append(transaction)
|
||||
|
||||
return {
|
||||
"status": "success",
|
||||
"message": "Payment processed successfully",
|
||||
"transaction_id": transaction_id
|
||||
}
|
||||
|
||||
def refund_payment(self, transaction_id):
|
||||
"""
|
||||
Refund a payment
|
||||
|
||||
Args:
|
||||
transaction_id (str): Transaction ID to refund
|
||||
|
||||
Returns:
|
||||
dict: Refund result
|
||||
"""
|
||||
transaction = next(
|
||||
(t for t in self.transactions if t["transaction_id"] == transaction_id),
|
||||
None
|
||||
)
|
||||
|
||||
if not transaction:
|
||||
return {
|
||||
"status": "failed",
|
||||
"message": "Transaction not found"
|
||||
}
|
||||
|
||||
if transaction.get("refunded"):
|
||||
return {
|
||||
"status": "failed",
|
||||
"message": "Transaction already refunded"
|
||||
}
|
||||
|
||||
transaction["refunded"] = True
|
||||
|
||||
return {
|
||||
"status": "success",
|
||||
"message": "Refund processed successfully",
|
||||
"transaction_id": transaction_id
|
||||
}
|
||||
|
||||
def get_transaction(self, transaction_id):
|
||||
"""
|
||||
Get transaction details
|
||||
|
||||
Args:
|
||||
transaction_id (str): Transaction ID
|
||||
|
||||
Returns:
|
||||
dict: Transaction details or None
|
||||
"""
|
||||
return next(
|
||||
(t for t in self.transactions if t["transaction_id"] == transaction_id),
|
||||
None
|
||||
)
|
||||
|
||||
def get_all_transactions(self):
|
||||
"""
|
||||
Get all transactions
|
||||
|
||||
Returns:
|
||||
list: All transactions
|
||||
"""
|
||||
return self.transactions.copy()
|
||||
1
tests/__init__.py
Normal file
1
tests/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
|||
# Test Package
|
||||
168
tests/test_payment.py
Normal file
168
tests/test_payment.py
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
"""
|
||||
Test cases for Payment Service
|
||||
"""
|
||||
import pytest
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Add src directory to path
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'src')))
|
||||
|
||||
from payment_service import PaymentService
|
||||
|
||||
|
||||
class TestPaymentService:
|
||||
"""Test suite for PaymentService"""
|
||||
|
||||
@pytest.fixture
|
||||
def payment_service(self):
|
||||
"""Create a fresh payment service instance for each test"""
|
||||
return PaymentService()
|
||||
|
||||
# Positive Test Cases
|
||||
|
||||
def test_successful_payment(self, payment_service):
|
||||
"""Test successful payment processing"""
|
||||
result = payment_service.process_payment(
|
||||
amount=100.50,
|
||||
card_number="1234567890123456",
|
||||
cvv="123"
|
||||
)
|
||||
|
||||
assert result["status"] == "success"
|
||||
assert result["transaction_id"] is not None
|
||||
assert result["message"] == "Payment processed successfully"
|
||||
|
||||
def test_multiple_payments(self, payment_service):
|
||||
"""Test processing multiple payments"""
|
||||
result1 = payment_service.process_payment(100.00, "1234567890123456", "123")
|
||||
result2 = payment_service.process_payment(200.00, "9876543210987654", "456")
|
||||
|
||||
assert result1["status"] == "success"
|
||||
assert result2["status"] == "success"
|
||||
assert result1["transaction_id"] != result2["transaction_id"]
|
||||
assert len(payment_service.get_all_transactions()) == 2
|
||||
|
||||
def test_get_transaction(self, payment_service):
|
||||
"""Test retrieving transaction details"""
|
||||
result = payment_service.process_payment(150.00, "1234567890123456", "123")
|
||||
transaction_id = result["transaction_id"]
|
||||
|
||||
transaction = payment_service.get_transaction(transaction_id)
|
||||
|
||||
assert transaction is not None
|
||||
assert transaction["transaction_id"] == transaction_id
|
||||
assert transaction["amount"] == 150.00
|
||||
|
||||
def test_successful_refund(self, payment_service):
|
||||
"""Test successful refund processing"""
|
||||
# First make a payment
|
||||
payment_result = payment_service.process_payment(100.00, "1234567890123456", "123")
|
||||
transaction_id = payment_result["transaction_id"]
|
||||
|
||||
# Then refund it
|
||||
refund_result = payment_service.refund_payment(transaction_id)
|
||||
|
||||
assert refund_result["status"] == "success"
|
||||
assert refund_result["message"] == "Refund processed successfully"
|
||||
|
||||
# Negative Test Cases
|
||||
|
||||
def test_invalid_amount_zero(self, payment_service):
|
||||
"""Test payment with zero amount"""
|
||||
result = payment_service.process_payment(0, "1234567890123456", "123")
|
||||
|
||||
assert result["status"] == "failed"
|
||||
assert result["message"] == "Invalid amount"
|
||||
assert result["transaction_id"] is None
|
||||
|
||||
def test_invalid_amount_negative(self, payment_service):
|
||||
"""Test payment with negative amount"""
|
||||
result = payment_service.process_payment(-50.00, "1234567890123456", "123")
|
||||
|
||||
assert result["status"] == "failed"
|
||||
assert result["message"] == "Invalid amount"
|
||||
|
||||
def test_invalid_card_number_short(self, payment_service):
|
||||
"""Test payment with short card number"""
|
||||
result = payment_service.process_payment(100.00, "123456", "123")
|
||||
|
||||
assert result["status"] == "failed"
|
||||
assert result["message"] == "Invalid card number"
|
||||
|
||||
def test_invalid_card_number_empty(self, payment_service):
|
||||
"""Test payment with empty card number"""
|
||||
result = payment_service.process_payment(100.00, "", "123")
|
||||
|
||||
assert result["status"] == "failed"
|
||||
assert result["message"] == "Invalid card number"
|
||||
|
||||
def test_invalid_cvv_short(self, payment_service):
|
||||
"""Test payment with short CVV"""
|
||||
result = payment_service.process_payment(100.00, "1234567890123456", "12")
|
||||
|
||||
assert result["status"] == "failed"
|
||||
assert result["message"] == "Invalid CVV"
|
||||
|
||||
def test_invalid_cvv_empty(self, payment_service):
|
||||
"""Test payment with empty CVV"""
|
||||
result = payment_service.process_payment(100.00, "1234567890123456", "")
|
||||
|
||||
assert result["status"] == "failed"
|
||||
assert result["message"] == "Invalid CVV"
|
||||
|
||||
def test_refund_nonexistent_transaction(self, payment_service):
|
||||
"""Test refunding a transaction that doesn't exist"""
|
||||
result = payment_service.refund_payment("TXN999999")
|
||||
|
||||
assert result["status"] == "failed"
|
||||
assert result["message"] == "Transaction not found"
|
||||
|
||||
def test_duplicate_refund(self, payment_service):
|
||||
"""Test refunding the same transaction twice"""
|
||||
# Make a payment
|
||||
payment_result = payment_service.process_payment(100.00, "1234567890123456", "123")
|
||||
transaction_id = payment_result["transaction_id"]
|
||||
|
||||
# First refund should succeed
|
||||
refund1 = payment_service.refund_payment(transaction_id)
|
||||
assert refund1["status"] == "success"
|
||||
|
||||
# Second refund should fail
|
||||
refund2 = payment_service.refund_payment(transaction_id)
|
||||
assert refund2["status"] == "failed"
|
||||
assert refund2["message"] == "Transaction already refunded"
|
||||
|
||||
# Edge Cases
|
||||
|
||||
def test_large_amount_payment(self, payment_service):
|
||||
"""Test payment with large amount"""
|
||||
result = payment_service.process_payment(999999.99, "1234567890123456", "123")
|
||||
|
||||
assert result["status"] == "success"
|
||||
|
||||
def test_small_amount_payment(self, payment_service):
|
||||
"""Test payment with small valid amount"""
|
||||
result = payment_service.process_payment(0.01, "1234567890123456", "123")
|
||||
|
||||
assert result["status"] == "success"
|
||||
|
||||
def test_get_all_transactions_empty(self, payment_service):
|
||||
"""Test getting all transactions when none exist"""
|
||||
transactions = payment_service.get_all_transactions()
|
||||
|
||||
assert transactions == []
|
||||
|
||||
def test_get_nonexistent_transaction(self, payment_service):
|
||||
"""Test getting a transaction that doesn't exist"""
|
||||
transaction = payment_service.get_transaction("TXN999999")
|
||||
|
||||
assert transaction is None
|
||||
|
||||
def test_card_number_masking(self, payment_service):
|
||||
"""Test that card numbers are properly masked in transactions"""
|
||||
payment_service.process_payment(100.00, "1234567890123456", "123")
|
||||
transaction = payment_service.get_all_transactions()[0]
|
||||
|
||||
assert transaction["card_number"] == "****3456"
|
||||
assert "1234567890123456" not in str(transaction)
|
||||
Loading…
Reference in New Issue
Block a user