Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/workflows/autopep8.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: autopep8 Check

on: [pull_request]

jobs:
autopep8-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"

- name: Install autopep8
run: pip install autopep8

- name: Check formatting with autopep8
id: check
run: |
# Check if autopep8 would make changes
formatting_issues=$(autopep8 --diff --recursive .)
Comment thread
JFoederer marked this conversation as resolved.
Outdated
if [[ formatting_issues ]] then
echo "Formatting issues found:"
printf "%s\n" "$formatting_issues"
echo "------------------------------"
echo "-- Formatting issues found! --"
echo "------------------------------"
exit 1
else
echo "No formatting issues found."
fi

31 changes: 31 additions & 0 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# This workflow will install Python dependencies, run tests and lint with a single version of Python
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python

name: Run Acceptance and Unit tests
Comment thread
osingaatje marked this conversation as resolved.

on:
pull_request:
branches: [ "main" ]

permissions:
contents: read

jobs:
build:

runs-on: ubuntu-latest
Comment thread
JFoederer marked this conversation as resolved.

steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v3
with:
python-version: "3.10"
Comment thread
JFoederer marked this conversation as resolved.
Outdated
- name: Install dependencies
run: |
python -m pip install --upgrade pip # upgrade pip to latest version
pip install . # install PyProject.toml dependencies - excludes optional dependencies (such as visualisation)!
- name: Test with pytest
run: |
python run_tests.py
Comment thread
osingaatje marked this conversation as resolved.

8 changes: 5 additions & 3 deletions atest/robotMBT tests/03__parse_model_info/MyProcessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ def process_test_suite(self, in_suite):
for scenario in in_suite.scenarios:
assert scenario.steps, msg
for step in scenario.steps:
assert step.model_info['IN'] == ['Alfa'], f"{msg} in step {step.keyword}"
assert step.model_info['OUT'] == ['Beta', 'Gamma delta', 'Epsilon'], f"{msg} in step {step.keyword}"
assert step.model_info['IN'] == [
'Alfa'], f"{msg} in step {step.keyword}"
assert step.model_info['OUT'] == [
'Beta', 'Gamma delta', 'Epsilon'], f"{msg} in step {step.keyword}"
return in_suite

def _fail_on_step_errors(self):
if self.in_suite.has_error():
msg = "\n".join(["Error(s) detected in at least one step"] +
[f"{step.kw_wo_gherkin} FAILED: {step.model_info['error']}"
for step in self.in_suite.steps_with_errors()])
for step in self.in_suite.steps_with_errors()])
raise Exception(msg)
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@

from robot.api.deco import library


@library(auto_keywords=None, listener=True)
class SuiteRepeater:
"""
Given a test suite, repeats all scenarios 'repeat' times (default=1)
Setting bonus_scenario=${True} repeats 1 additional time
sub-suites are ignored
"""

def process_test_suite(self, in_suite, repeat=1, **kwargs):
n_repeats = int(repeat)
if kwargs.get('bonus_scenario', False):
n_repeats +=1
n_repeats += 1
out_suite = copy.deepcopy(in_suite)
out_suite.scenarios = n_repeats*out_suite.scenarios
for i in range(len(out_suite.scenarios)):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
from robot.api.deco import keyword


class traces:
ROBOT_LIBRARY_SCOPE = 'GLOBAL'

def reset_traces(self):
self.traces = {}

@keyword("Trace '${trace}', scenario number ${test_id} is executed")
def add_test(self, trace, test_id:str):
def add_test(self, trace, test_id: str):
"""*model info*
:IN: None
:OUT: None
Expand Down
22 changes: 15 additions & 7 deletions demo/Titanic/domain_lib/JourneyLib.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from simulation.titanic_in_ocean import TitanicInOcean
from simulation.journey import Journey


class JourneyLib:
_journey = None

Expand All @@ -31,11 +32,13 @@ def map_lib(self) -> MapLib:
def start_journey(self, date: str):
date = datetime.strptime(date, "%Y-%m-%d")
self.journey.start_date = date
self.builtin.log(f"The journey has started at {self.journey.start_date.strftime('%Y-%m-%d')}")
self.builtin.log(
f"The journey has started at {self.journey.start_date.strftime('%Y-%m-%d')}")

@keyword("Current date of Journey")
def journey_ondate(self):
current_date = self.journey.start_date + timedelta(minutes=self.journey.time_in_journey)
current_date = self.journey.start_date + \
timedelta(minutes=self.journey.time_in_journey)
return current_date.strftime('%Y-%m-%d')

@keyword("play out Journey for a duration of ${minutes} minutes")
Expand All @@ -46,21 +49,26 @@ def pass_time(self, minutes: int):
"""
self.journey.passed_time(minutes)
if self.call_count % 100 == 0:
map_animation.update_floating_objects(self.journey.ocean.floating_objects)
map_animation.update_floating_objects(
self.journey.ocean.floating_objects)
self.call_count += 1

@keyword("Move Titanic out of current area")
def move_titanic_out_of_current_area(self):
titanic = TitanicInOcean.instance
current_area = self.builtin.run_keyword("Area of location Titanic's position")
current_area = self.builtin.run_keyword(
"Area of location Titanic's position")
self.builtin.log(f"Titanic moving out of {current_area}")
while (new_area := self.map_lib.get_area_of_location(titanic)) == current_area:
if not titanic.speed > 0:
self.builtin.log(f"Titanic not moving. Still in area {new_area}")
self.builtin.log(
f"Titanic not moving. Still in area {new_area}")
break
self.pass_time(1)
if titanic.fell_off_the_earth():
raise Exception("Titanic at least did not sink. But where did it go?")
raise Exception(
"Titanic at least did not sink. But where did it go?")
else:
self.builtin.log(f"Titanic moved into {new_area}")
map_animation.update_floating_objects(self.journey.ocean.floating_objects)
map_animation.update_floating_objects(
self.journey.ocean.floating_objects)
3 changes: 2 additions & 1 deletion demo/Titanic/domain_lib/MapLib.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ def __init__(self):
'Iceberg alley': AreaOnGrid(LocationOnGrid(latitude=43, longitude=-45), LocationOnGrid(latitude=48, longitude=-50))
}

atlantic_area = AreaOnGrid(LocationOnGrid(latitude=35, longitude=-1.41), LocationOnGrid(latitude=65, longitude=-74))
atlantic_area = AreaOnGrid(LocationOnGrid(
latitude=35, longitude=-1.41), LocationOnGrid(latitude=65, longitude=-74))

LOCATION_AREA_THRESHOLD = 0.1
ATLANTIC_AREA = 'Atlantic'
Expand Down
15 changes: 10 additions & 5 deletions demo/Titanic/domain_lib/TitanicLib.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ def point_titanic_towards(self, location):
if titanic.sunk:
self.builtin.log(f"Pointing towards Davy Jones' locker")
return
port_location = self.builtin.run_keyword(f"Location of port {location}")
port_location = self.builtin.run_keyword(
f"Location of port {location}")
new_direction = titanic.calculate_direction(port_location)

titanic.direction = new_direction
Expand All @@ -34,7 +35,8 @@ def point_titanic_towards(self, location):
def titanic_stops(self):
titanic = TitanicInOcean.instance
titanic.titanic.throttle = 0
titanic.speed = 0 # TODO should happen over time (due to throttle being > 0)
# TODO should happen over time (due to throttle being > 0)
titanic.speed = 0
self.builtin.log("Now it is time for Titanic to stop at new location")

@keyword("Titanic moves full speed ahead")
Expand All @@ -44,13 +46,16 @@ def titanic_full_speed(self):
self.builtin.log(f"There seems to be an issue with the throttle")
return
titanic.titanic.throttle = 1
titanic.speed = 700 # TODO Figure out what this speed means. Does time calculation make sense?!?!
self.builtin.log(f"Here we go through the new location with speed {titanic.speed}")
# TODO Figure out what this speed means. Does time calculation make sense?!?!
titanic.speed = 700
self.builtin.log(
f"Here we go through the new location with speed {titanic.speed}")

@keyword("Titanic's position")
def titanic_location(self):
titanic = TitanicInOcean.instance
loc = LocationOnGrid(longitude=titanic.longitude, latitude=titanic.latitude)
loc = LocationOnGrid(longitude=titanic.longitude,
latitude=titanic.latitude)
self.builtin.log(f"Titanic's current position is: {loc}")
return loc

Expand Down
8 changes: 5 additions & 3 deletions demo/Titanic/run_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@
THIS_DIR = os.path.dirname(os.path.abspath(__file__))
OUTPUT_ROOT = os.path.join(THIS_DIR, 'results')
SCENARIO_FOLDER = os.path.join(THIS_DIR, 'Titanic_scenarios')
HIT_MISS_TAG = 'hit' if len(sys.argv) == 1 or sys.argv[1].casefold() != 'hit' else 'miss'
EXTENDED_TAG = 'extended' if len(sys.argv) == 1 or sys.argv[1].casefold() != 'extended' else 'dummy'
HIT_MISS_TAG = 'hit' if len(
sys.argv) == 1 or sys.argv[1].casefold() != 'hit' else 'miss'
EXTENDED_TAG = 'extended' if len(
sys.argv) == 1 or sys.argv[1].casefold() != 'extended' else 'dummy'

# The base folder needs to be added to the python path to resolve the dependencies. You
# will also need to add this path to your IDE options when running from there.
Expand All @@ -27,4 +29,4 @@
'--exclude', EXTENDED_TAG,
'--loglevel', 'DEBUG:INFO',
SCENARIO_FOLDER],
exit=False)
exit=False)
27 changes: 17 additions & 10 deletions demo/Titanic/run_game.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
'Iceberg alley': AreaOnGrid(LocationOnGrid(latitude=43, longitude=-45), LocationOnGrid(latitude=48, longitude=-50))
}

atlantic_area = AreaOnGrid(LocationOnGrid(latitude=35, longitude=-1.41), LocationOnGrid(latitude=65, longitude=-74))
atlantic_area = AreaOnGrid(LocationOnGrid(
latitude=35, longitude=-1.41), LocationOnGrid(latitude=65, longitude=-74))


def run_game(map_animation, journey, tio: TitanicInOcean, atlantic_area):

Expand All @@ -35,7 +37,8 @@ def main_game_loop(stdscr):
# Set up the window
stdscr.nodelay(True) # Non-blocking input
stdscr.timeout(100) # Refresh every 100 milliseconds
stdscr.addstr(0, 0, "Q=Quit. 0=Stop Titanic. WASD-controls (WS control speed, AD control rotation, no need to press and hold)")
stdscr.addstr(
0, 0, "Q=Quit. 0=Stop Titanic. WASD-controls (WS control speed, AD control rotation, no need to press and hold)")

objective = 1
iceberg_alley_reached = False
Expand All @@ -44,7 +47,8 @@ def main_game_loop(stdscr):
while True:
journey.passed_time(100)

map_animation.update_floating_objects(journey.ocean.floating_objects)
map_animation.update_floating_objects(
journey.ocean.floating_objects)

if not atlantic_area.is_location_within_area(tio):
tio.direction -= 180
Expand All @@ -55,15 +59,19 @@ def main_game_loop(stdscr):
if areas['Iceberg alley'].is_location_within_area(tio):
iceberg_alley_reached = True
elif iceberg_alley_reached:
stdscr.addstr(objective, 0, "Objective 1: Safely cross Iceberg Alley [Achieved]")
stdscr.addstr(
objective, 0, "Objective 1: Safely cross Iceberg Alley [Achieved]")
objective = 2
stdscr.addstr(objective, 0, "Objective 2: Sail to New York")
stdscr.addstr(
objective, 0, "Objective 2: Sail to New York")
elif objective == 2:
if tio.distance_to(locations['New York']) < 0.5:
tio.speed = 0
stdscr.addstr(objective, 0, "Objective 2: Sail to New York [Achieved]")
stdscr.addstr(
objective, 0, "Objective 2: Sail to New York [Achieved]")
objective = 4
stdscr.addstr(objective, 0, "You made it to New York!! Press Q to exit.")
stdscr.addstr(
objective, 0, "You made it to New York!! Press Q to exit.")

if tio.sunk:
stdscr.addstr(objective+2, 0,
Expand Down Expand Up @@ -97,7 +105,6 @@ def main_game_loop(stdscr):

# Continue with the rest of the game logic


# Initialize curses
stdscr = curses.initscr()
curses.noecho() # Disable automatic echoing of pressed keys
Expand Down Expand Up @@ -127,7 +134,8 @@ def main_game_loop(stdscr):
location = locations["Southampton"]

t = Titanic(0, steering_direction=0)
tio = TitanicInOcean(t, longitude=location.longitude - 1, latitude=location.latitude, speed=0, direction=270)
tio = TitanicInOcean(t, longitude=location.longitude - 1,
latitude=location.latitude, speed=0, direction=270)
ocean.floating_objects.append(tio)

iceberg = Iceberg(latitude=45.5, longitude=-47.5)
Expand All @@ -138,4 +146,3 @@ def main_game_loop(stdscr):
map_animation.update_floating_objects(ocean.floating_objects)

run_game(map_animation, journey, tio, atlantic_area)

2 changes: 2 additions & 0 deletions demo/Titanic/simulation/journey.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ class StatusOfJourney(Enum):
ON_THE_WAY = 2
ARRIVED = 3
SUNK = 4


class Journey:

_instance = None
Expand Down
Loading