mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-04-26 09:16:21 +02:00
Merge branch 'main' into feature/teacher
This commit is contained in:
commit
28c3bfd036
30 changed files with 800 additions and 129 deletions
|
|
@ -9,15 +9,147 @@ import pytest
|
|||
|
||||
from metagpt.actions.debug_error import DebugError
|
||||
|
||||
EXAMPLE_MSG_CONTENT = '''
|
||||
---
|
||||
## Development Code File Name
|
||||
player.py
|
||||
## Development Code
|
||||
```python
|
||||
from typing import List
|
||||
from deck import Deck
|
||||
from card import Card
|
||||
|
||||
class Player:
|
||||
"""
|
||||
A class representing a player in the Black Jack game.
|
||||
"""
|
||||
|
||||
def __init__(self, name: str):
|
||||
"""
|
||||
Initialize a Player object.
|
||||
|
||||
Args:
|
||||
name (str): The name of the player.
|
||||
"""
|
||||
self.name = name
|
||||
self.hand: List[Card] = []
|
||||
self.score = 0
|
||||
|
||||
def draw(self, deck: Deck):
|
||||
"""
|
||||
Draw a card from the deck and add it to the player's hand.
|
||||
|
||||
Args:
|
||||
deck (Deck): The deck of cards.
|
||||
"""
|
||||
card = deck.draw_card()
|
||||
self.hand.append(card)
|
||||
self.calculate_score()
|
||||
|
||||
def calculate_score(self) -> int:
|
||||
"""
|
||||
Calculate the score of the player's hand.
|
||||
|
||||
Returns:
|
||||
int: The score of the player's hand.
|
||||
"""
|
||||
self.score = sum(card.value for card in self.hand)
|
||||
# Handle the case where Ace is counted as 11 and causes the score to exceed 21
|
||||
if self.score > 21 and any(card.rank == 'A' for card in self.hand):
|
||||
self.score -= 10
|
||||
return self.score
|
||||
|
||||
```
|
||||
## Test File Name
|
||||
test_player.py
|
||||
## Test Code
|
||||
```python
|
||||
import unittest
|
||||
from blackjack_game.player import Player
|
||||
from blackjack_game.deck import Deck
|
||||
from blackjack_game.card import Card
|
||||
|
||||
class TestPlayer(unittest.TestCase):
|
||||
## Test the Player's initialization
|
||||
def test_player_initialization(self):
|
||||
player = Player("Test Player")
|
||||
self.assertEqual(player.name, "Test Player")
|
||||
self.assertEqual(player.hand, [])
|
||||
self.assertEqual(player.score, 0)
|
||||
|
||||
## Test the Player's draw method
|
||||
def test_player_draw(self):
|
||||
deck = Deck()
|
||||
player = Player("Test Player")
|
||||
player.draw(deck)
|
||||
self.assertEqual(len(player.hand), 1)
|
||||
self.assertEqual(player.score, player.hand[0].value)
|
||||
|
||||
## Test the Player's calculate_score method
|
||||
def test_player_calculate_score(self):
|
||||
deck = Deck()
|
||||
player = Player("Test Player")
|
||||
player.draw(deck)
|
||||
player.draw(deck)
|
||||
self.assertEqual(player.score, sum(card.value for card in player.hand))
|
||||
|
||||
## Test the Player's calculate_score method with Ace card
|
||||
def test_player_calculate_score_with_ace(self):
|
||||
deck = Deck()
|
||||
player = Player("Test Player")
|
||||
player.hand.append(Card('A', 'Hearts', 11))
|
||||
player.hand.append(Card('K', 'Hearts', 10))
|
||||
player.calculate_score()
|
||||
self.assertEqual(player.score, 21)
|
||||
|
||||
## Test the Player's calculate_score method with multiple Aces
|
||||
def test_player_calculate_score_with_multiple_aces(self):
|
||||
deck = Deck()
|
||||
player = Player("Test Player")
|
||||
player.hand.append(Card('A', 'Hearts', 11))
|
||||
player.hand.append(Card('A', 'Diamonds', 11))
|
||||
player.calculate_score()
|
||||
self.assertEqual(player.score, 12)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
```
|
||||
## Running Command
|
||||
python tests/test_player.py
|
||||
## Running Output
|
||||
standard output: ;
|
||||
standard errors: ..F..
|
||||
======================================================================
|
||||
FAIL: test_player_calculate_score_with_multiple_aces (__main__.TestPlayer)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "tests/test_player.py", line 46, in test_player_calculate_score_with_multiple_aces
|
||||
self.assertEqual(player.score, 12)
|
||||
AssertionError: 22 != 12
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 5 tests in 0.007s
|
||||
|
||||
FAILED (failures=1)
|
||||
;
|
||||
## instruction:
|
||||
The error is in the development code, specifically in the calculate_score method of the Player class. The method is not correctly handling the case where there are multiple Aces in the player's hand. The current implementation only subtracts 10 from the score once if the score is over 21 and there's an Ace in the hand. However, in the case of multiple Aces, it should subtract 10 for each Ace until the score is 21 or less.
|
||||
## File To Rewrite:
|
||||
player.py
|
||||
## Status:
|
||||
FAIL
|
||||
## Send To:
|
||||
Engineer
|
||||
---
|
||||
'''
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_debug_error():
|
||||
code = "def add(a, b):\n return a - b"
|
||||
error = "AssertionError: Expected add(1, 1) to equal 2 but got 0"
|
||||
|
||||
debug_error = DebugError("debug_error")
|
||||
|
||||
result = await debug_error.run(code, error)
|
||||
file_name, rewritten_code = await debug_error.run(context=EXAMPLE_MSG_CONTENT)
|
||||
|
||||
# mock_llm.ask.assert_called_once_with(prompt)
|
||||
assert len(result) > 0
|
||||
assert "class Player" in rewritten_code # rewrite the same class
|
||||
assert "while self.score > 21" in rewritten_code # a key logic to rewrite to (original one is "if self.score > 12")
|
||||
|
|
|
|||
|
|
@ -6,33 +6,65 @@
|
|||
@File : test_run_code.py
|
||||
"""
|
||||
import pytest
|
||||
|
||||
import asyncio
|
||||
from metagpt.actions.run_code import RunCode
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_run_text():
|
||||
action = RunCode()
|
||||
result, errs = await RunCode.run_text('result = 1 + 1')
|
||||
assert result == 2
|
||||
assert errs == ""
|
||||
|
||||
result, errs = await RunCode.run_text('result = 1 / 0')
|
||||
assert result == ""
|
||||
assert "ZeroDivisionError" in errs
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_run_code():
|
||||
code = """
|
||||
def add(a, b):
|
||||
return a + b
|
||||
result = add(1, 2)
|
||||
"""
|
||||
run_code = RunCode("run_code")
|
||||
|
||||
result = await run_code.run(code)
|
||||
|
||||
assert result == 3
|
||||
async def test_run_script():
|
||||
action = RunCode()
|
||||
|
||||
# Successful command
|
||||
out, err = await RunCode.run_script(".", command=["echo", "Hello World"])
|
||||
assert out.strip() == "Hello World"
|
||||
assert err == ""
|
||||
|
||||
# Unsuccessful command
|
||||
out, err = await RunCode.run_script(".", command=["python", "-c", "print(1/0)"])
|
||||
assert "ZeroDivisionError" in err
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_run_code_with_error():
|
||||
code = """
|
||||
def add(a, b):
|
||||
return a + b
|
||||
result = add(1, '2')
|
||||
"""
|
||||
run_code = RunCode("run_code")
|
||||
async def test_run():
|
||||
action = RunCode()
|
||||
result = await action.run(mode="text", code="print('Hello, World')")
|
||||
assert "PASS" in result
|
||||
|
||||
result = await run_code.run(code)
|
||||
result = await action.run(
|
||||
mode="script",
|
||||
code="echo 'Hello World'",
|
||||
code_file_name="",
|
||||
test_code="",
|
||||
test_file_name="",
|
||||
command=["echo", "Hello World"],
|
||||
working_directory=".",
|
||||
additional_python_paths=[]
|
||||
)
|
||||
assert "PASS" in result
|
||||
|
||||
assert "TypeError: unsupported operand type(s) for +" in result
|
||||
@pytest.mark.asyncio
|
||||
async def test_run_failure():
|
||||
action = RunCode()
|
||||
result = await action.run(mode="text", code="result = 1 / 0")
|
||||
assert "FAIL" in result
|
||||
|
||||
result = await action.run(
|
||||
mode="script",
|
||||
code='python -c "print(1/0)"',
|
||||
code_file_name="",
|
||||
test_code="",
|
||||
test_file_name="",
|
||||
command=["python", "-c", "print(1/0)"],
|
||||
working_directory=".",
|
||||
additional_python_paths=[]
|
||||
)
|
||||
assert "FAIL" in result
|
||||
|
|
@ -8,19 +8,35 @@
|
|||
import pytest
|
||||
|
||||
from metagpt.actions.write_test import WriteTest
|
||||
from metagpt.logs import logger
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_write_test():
|
||||
code = """
|
||||
def add(a, b):
|
||||
return a + b
|
||||
import random
|
||||
from typing import Tuple
|
||||
|
||||
class Food:
|
||||
def __init__(self, position: Tuple[int, int]):
|
||||
self.position = position
|
||||
|
||||
def generate(self, max_y: int, max_x: int):
|
||||
self.position = (random.randint(1, max_y - 1), random.randint(1, max_x - 1))
|
||||
"""
|
||||
|
||||
write_test = WriteTest("write_test")
|
||||
write_test = WriteTest()
|
||||
|
||||
test_cases = await write_test.run(code)
|
||||
test_code = await write_test.run(
|
||||
code_to_test=code,
|
||||
test_file_name="test_food.py",
|
||||
source_file_path="/some/dummy/path/cli_snake_game/cli_snake_game/food.py",
|
||||
workspace="/some/dummy/path/cli_snake_game"
|
||||
)
|
||||
logger.info(test_code)
|
||||
|
||||
# We cannot exactly predict the generated test cases, but we can check if it is a string and if it is not empty
|
||||
assert isinstance(test_cases, str)
|
||||
assert len(test_cases) > 0
|
||||
assert isinstance(test_code, str)
|
||||
assert "from cli_snake_game.food import Food" in test_code
|
||||
assert "class TestFood(unittest.TestCase)" in test_code
|
||||
assert "def test_generate" in test_code
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue