Skip to content

Commit 75df748

Browse files
committed
test(main): Add unit tests for Helm template generation and IaC workflows (basic, bugfix, install, template) with pytest and mocker, and update README with testing instructions.
1 parent acf28db commit 75df748

7 files changed

Lines changed: 217 additions & 25 deletions

File tree

README.md

Lines changed: 48 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,84 @@
11
# DevOps-GPT
2+
23
Use a brilliant assistant as your friend in your DevOps Journey.
34

45
## What does this project offer?
5-
This project helps you to balance your daily work as a DevOps engineer, from simple bug fixes to project template generation.<br />
6-
you don't need to search on Google for some routine jobs and it helps you with a robust prompt to simplify your career.
6+
7+
This project helps you to balance your daily work as a DevOps engineer, from simple bug fixes to project template generation.
8+
You don't need to search on Google for some routine jobs, and it helps you with a robust prompt to simplify your career.
79

810
## How it works?
9-
This is a wrapper between DevOps engineers and large language models like GPT-4-mini. The main strength of it is prompt engineering.<br />
1011

11-
We have developed some (Extendable) prompt-driven solutions with a simplified interface for the DevOps process cost reduction.<br />
12+
This is a wrapper between DevOps engineers and large language models like GPT-4-mini. The main strength of it is prompt engineering.
13+
14+
We have developed some (extendable) prompt-driven solutions with a simplified interface for the DevOps process cost reduction.
1215

1316
### Docker services
14-
We run our services using docker-compose (the main Fast-API-based backend and MongoDB), so we package all dependencies and don't use any external service.<br />
15-
The second one is Mongodb. we need to save the prompt and GPT-4_mini response in the Mongo document for future use. (for example, fine-tuning the other model with our data) <br />
17+
18+
We run our services using docker-compose (the main Fast-API-based backend and MongoDB), so we package all dependencies and don't use any external service.
19+
The second one is MongoDB. We need to save the prompt and GPT-4-mini response in the Mongo document for future use (e.g., fine-tuning another model with our data).
1620

1721
### Media directory
18-
The third one is in the media directory. for now, We save a project called (MyTerraform) which is a Terraform template generated based on user requirements. so users can download it and use it.<be />
19-
surely we can save any static data in the `/media`.
2022

21-
![teramedia](https://github.com/user-attachments/assets/b8e10d83-68ac-4efc-b064-45f1d1a870dc)
23+
The third one is the media directory. For now, we save a project called (MyTerraform), which is a Terraform template generated based on user requirements, so users can download it and use it.
24+
Surely we can save any static data in the `/media`.
2225

2326
This is an example of a template generated in the `/media`
2427

25-
and the input is something like that
26-
27-
![Screenshot from 2024-10-27 10-56-54](https://github.com/user-attachments/assets/63d1db07-2c25-4c10-a841-69a2c1235d9d)
28-
29-
28+
The input is something like this:
3029

3130
### directory_generators
32-
This directory becomes updated when we trigger the template generation API. finally, It generates the MyTerraform directory based on user input which is a template.
3331

32+
This directory gets updated when we trigger the template generation API. Finally, it generates the MyTerraform directory based on user input, which is a template.
3433

3534
## ToolChain
35+
3636
1. Python
3737
2. Docker
38-
3. GPT-4o-mini
38+
3. GPT-4-mini
3939
4. FastAPI
4040
5. Helm
4141

4242
## Pre-requisites
43+
4344
1. Python
4445
2. Docker
4546

4647
## How to use?
47-
execute `sh run.sh` in your terminal
4848

49-
> [!WARNING]
50-
> Do Not change the GPT model! Prompts have been developed for the GPT-4-mini model and they can't be integrated with other GPT models. it can cause horrible incompatibility.
49+
Execute `sh run.sh` in your terminal
50+
51+
> [!WARNING]\
52+
> Do Not change the GPT model! Prompts have been developed for the GPT-4-mini model, and they can't be integrated with other GPT models. It can cause horrible incompatibility.
5153
52-
## Run it local on kubernetes
53-
If you want to run and use this chatbot app within your Kubernetes cluster, you can easily install it using the Helm chart provided in this repository
54+
## Run it locally on Kubernetes
5455

55-
helm install [RELEASE_NAME] helm/ -f helm/values.yaml
56+
If you want to run and use this chatbot app within your Kubernetes cluster, you can easily install it using the Helm chart provided in this repository:
57+
58+
```
59+
helm install [RELEASE_NAME] helm/ -f helm/values.yaml
60+
```
61+
62+
## Tests
63+
64+
We have added unit tests to ensure the stability and reliability of the project.
65+
66+
### Running Tests
67+
68+
To run the tests, use the following command:
69+
70+
```
71+
cd app
72+
pytest tests/
73+
```
74+
75+
This command will execute all the test cases present in the `tests` folder. The tests include validation of the API endpoints, ensuring correct interactions with GPT services, and verifying that the generated outputs meet expected standards.
5676

5777
# Contributing
58-
please read the [Contribution guide](https://github.com/abolfazl8131/devops-gpt/blob/master/CONTRIBUTING.md)
78+
79+
Please read the [Contribution guide](https://github.com/abolfazl8131/devops-gpt/blob/master/CONTRIBUTING.md)
80+
5981
# Maintenance
60-
** [Abolfazl Andalib](https://github.com/abolfazl8131) - abolfazlandalib@gmail.com **<br />
61-
** [Mohammad Madanipour](https://github.com/mohammadll) - m.madanipourr@gmail.com **
82+
83+
**[Abolfazl Andalib](https://github.com/abolfazl8131)** - [abolfazlandalib@gmail.com](mailto:abolfazlandalib@gmail.com)
84+
**[Mohammad Madanipour](https://github.com/mohammadll)** - [m.madanipourr@gmail.com](mailto:m.madanipourr@gmail.com)

app/tests/__init__.py

Whitespace-only changes.

app/tests/test_helm_template.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import pytest
2+
from unittest.mock import patch
3+
from fastapi.testclient import TestClient
4+
from app.main import app
5+
from app.models import HelmTemplateGeneration, Pod, Persistance, Ingress
6+
7+
client = TestClient(app)
8+
9+
@pytest.fixture
10+
def sample_helm_template_input():
11+
return HelmTemplateGeneration(
12+
api_version="3",
13+
pods=[
14+
Pod(name="nginx", image="nginx:latest", target_port=80, replicas=2, persistance=Persistance(enabled=False), environment=[{"name": "DEBUG", "value": "true"}], stateless=True, ingress=Ingress(enabled=True)),
15+
Pod(name="redis", image="redis:latest", target_port=6379, replicas=1, persistance=Persistance(enabled=True), environment=[], stateless=False, ingress=Ingress(enabled=False))
16+
]
17+
)
18+
19+
@patch("app.main.gpt_service")
20+
@patch("app.main.edit_directory_generator")
21+
@patch("app.main.execute_pythonfile")
22+
def test_helm_template_generation(mock_execute_pythonfile, mock_edit_directory_generator, mock_gpt_service, sample_helm_template_input):
23+
mock_gpt_service.return_value = "Generated Python Code"
24+
25+
response = client.post("/Helm-template/", json=sample_helm_template_input.dict())
26+
27+
assert response.status_code == 200
28+
assert response.json()["output"] == "output"
29+
30+
mock_gpt_service.assert_called_once()
31+
mock_edit_directory_generator.assert_called_once_with("helm_generator", "Generated Python Code")
32+
mock_execute_pythonfile.assert_called_once_with("MyHelm", "helm_generator")

app/tests/test_iac_basic.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import pytest
2+
from fastapi.testclient import TestClient
3+
from unittest.mock import patch
4+
from app.main import app
5+
from app.models import IaCBasicInput
6+
7+
client = TestClient(app)
8+
mocked_gpt_response = "Mocked GPT response for IaC-basic"
9+
10+
@pytest.fixture
11+
def valid_basic_data():
12+
return IaCBasicInput(
13+
input="Create a basic configuration",
14+
service="terraform",
15+
min_tokens=100,
16+
max_tokens=500
17+
)
18+
19+
@patch('app.main.gpt_service', return_value=mocked_gpt_response)
20+
def test_iac_basic_generation(mock_gpt_service, valid_basic_data):
21+
"""
22+
Test the /IaC-basic/ endpoint with valid input data.
23+
"""
24+
response = client.post("/IaC-basic/", json=valid_basic_data.model_dump())
25+
assert response.status_code == 200
26+
assert response.json() == {"output": mocked_gpt_response}
27+
28+
expected_prompt = """
29+
Write a robust answer about terraform,
30+
focusing on the latest update of terraform and based on this question:Create a basic configuration,
31+
minimun length of answer is 100 and maximum length is 500
32+
"""
33+
actual_prompt = " ".join(mock_gpt_service.call_args[0][0].split())
34+
normalized_expected_prompt = " ".join(expected_prompt.split())
35+
assert actual_prompt == normalized_expected_prompt

app/tests/test_iac_bugfix.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import pytest
2+
from fastapi.testclient import TestClient
3+
from unittest.mock import patch
4+
from app.main import app
5+
from app.models import IaCBugfixInput
6+
7+
client = TestClient(app)
8+
mocked_gpt_response = "Mocked GPT response for IaC-bugfix"
9+
10+
@pytest.fixture
11+
def valid_bugfix_data():
12+
return IaCBugfixInput(
13+
input="Fix the deployment issue",
14+
bug_description="Application fails to start on version 1.2.3",
15+
version="1.2.3",
16+
service="terraform",
17+
min_tokens=100,
18+
max_tokens=500
19+
)
20+
21+
@patch('app.main.gpt_service', return_value=mocked_gpt_response)
22+
def test_iac_bugfix_generation(mock_gpt_service, valid_bugfix_data):
23+
"""
24+
Test the /IaC-bugfix/ endpoint with valid input data to ensure correct output.
25+
"""
26+
response = client.post("/IaC-bugfix/", json=valid_bugfix_data.model_dump())
27+
assert response.status_code == 200
28+
assert response.json() == {"output": mocked_gpt_response}
29+
30+
expected_prompt = """
31+
Write a clear answer to debug terraform
32+
focusing on the version 1.2.3 of terraform and based on this bug:Application fails to start on version 1.2.3,
33+
generate a correct code that help us to solve this bug.
34+
minimun length of answer is 100 and maximum length is 500
35+
"""
36+
actual_prompt = " ".join(mock_gpt_service.call_args[0][0].split())
37+
normalized_expected_prompt = " ".join(expected_prompt.split())
38+
assert actual_prompt == normalized_expected_prompt

app/tests/test_iac_install.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import pytest
2+
from fastapi.testclient import TestClient
3+
from unittest.mock import patch
4+
from app.main import app
5+
from app.models import IaCInstallationInput
6+
7+
client = TestClient(app)
8+
mocked_gpt_response = "Mocked shell script for installing terraform on Ubuntu."
9+
10+
@pytest.fixture
11+
def valid_installation_data():
12+
return IaCInstallationInput(
13+
os="ubuntu",
14+
service="terraform",
15+
min_tokens=100,
16+
max_tokens=500
17+
)
18+
19+
@patch('app.main.gpt_service', return_value=mocked_gpt_response)
20+
def test_iac_install_generation(mock_gpt_service, valid_installation_data):
21+
"""
22+
Test the /IaC-install/ endpoint with valid input data to ensure correct output.
23+
"""
24+
response = client.post("/IaC-install/", json=valid_installation_data.model_dump())
25+
assert response.status_code == 200
26+
assert response.json() == {"output": mocked_gpt_response}
27+
28+
expected_prompt = """
29+
generate a clear shell acript about installation terraform in ubuntu based on terraform document.
30+
without any additional note. just script for installation.
31+
"""
32+
actual_prompt = " ".join(mock_gpt_service.call_args[0][0].split())
33+
normalized_expected_prompt = " ".join(expected_prompt.split())
34+
assert actual_prompt == normalized_expected_prompt

app/tests/test_iac_template.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import pytest
2+
from unittest.mock import patch
3+
from fastapi.testclient import TestClient
4+
from app.main import app
5+
from app.models import IaCTemplateGeneration
6+
7+
client = TestClient(app)
8+
9+
@pytest.fixture
10+
def sample_iac_template_input():
11+
return IaCTemplateGeneration(
12+
service="MyService",
13+
CI_integration=True,
14+
base_config="BasicConfig"
15+
)
16+
17+
@patch("app.main.gpt_service")
18+
@patch("app.main.edit_directory_generator")
19+
@patch("app.main.execute_pythonfile")
20+
def test_iac_template_generation(mock_execute_pythonfile, mock_edit_directory_generator, mock_gpt_service, sample_iac_template_input):
21+
mock_gpt_service.return_value = "Generated Python Code"
22+
23+
response = client.post("/IaC-template/", json=sample_iac_template_input.dict())
24+
25+
assert response.status_code == 200
26+
assert response.json()["output"] == "output"
27+
28+
mock_gpt_service.assert_called_once()
29+
mock_edit_directory_generator.assert_called_once_with("terraform_generator", "Generated Python Code")
30+
mock_execute_pythonfile.assert_called_once_with("MyTerraform", "terraform_generator")

0 commit comments

Comments
 (0)