+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.project b/.project
new file mode 100644
index 0000000..86e9bfc
--- /dev/null
+++ b/.project
@@ -0,0 +1,23 @@
+
+
+ de.devboost.natspec.example.python
+
+
+
+
+
+ org.python.pydev.PyDevBuilder
+
+
+
+
+ de.devboost.natspec.resource.natspec.builder
+
+
+
+
+
+ org.python.pydev.pythonNature
+ de.devboost.natspec.resource.natspec.nature
+
+
diff --git a/.pydevproject b/.pydevproject
new file mode 100644
index 0000000..037bd25
--- /dev/null
+++ b/.pydevproject
@@ -0,0 +1,8 @@
+
+
+
+/${PROJECT_DIR_NAME}
+
+python 2.7
+Default
+
diff --git a/.svn/entries b/.svn/entries
new file mode 100644
index 0000000..3cacc0b
--- /dev/null
+++ b/.svn/entries
@@ -0,0 +1 @@
+12
\ No newline at end of file
diff --git a/.svn/format b/.svn/format
new file mode 100644
index 0000000..3cacc0b
--- /dev/null
+++ b/.svn/format
@@ -0,0 +1 @@
+12
\ No newline at end of file
diff --git a/.svn/pristine/03/033e7a2a281fed1f658eae89afff72756789b9b1.svn-base b/.svn/pristine/03/033e7a2a281fed1f658eae89afff72756789b9b1.svn-base
new file mode 100644
index 0000000..95d1b9b
--- /dev/null
+++ b/.svn/pristine/03/033e7a2a281fed1f658eae89afff72756789b9b1.svn-base
@@ -0,0 +1,72 @@
+from natspec_utils.stringutils import stringToUnicode as u;
+
+import unittest
+from test.support import TestSupport
+from service.airline_service import AirlineService
+from persistence.in_memory_context import InMemoryPersistenceContext
+
+class OverbookSeatNumber(unittest.TestCase):
+ """This class serves as a template for all classes that are generated for
+ NatSpec scenarios (.natspec files). It is recognized by NatSpec based on its
+ special name and applies to all scenarios in the same package and all sub
+ packages (unless there is another template class in one of the sub packages).
+ This particular template is a unittest test case where the concrete steps of the
+ test are filled by the NatSpec code generator.
+ """
+
+ def setUp(self):
+ """Sets up the test environment (i.e., initialize the service class, the
+ entity manager and the test support class).
+ """
+ self.service = AirlineService()
+ self.persistence_context = InMemoryPersistenceContext()
+ self.test_support = TestSupport(self.service, self.persistence_context, self)
+
+ def test(self):
+ """
+ The code in this method is generated from: /de.devboost.natspec.example.python/test/scenarios/overbook_seat_number.natspec
+ Never change this method or any contents of this file, all local changes will we overwritten.
+ """
+ # Given an airplane Boeing-737-600
+ airplaneType_Boeing_737_600 = self.test_support.given_an_airplane(u("Boeing-737-600"))
+
+ # Given a flight LH-1234
+ flight_LH_1234 = self.test_support.given_a_flight(u("LH-1234"))
+
+ # that is executed using a Boeing-737-600
+ self.test_support.that_is_executed_using_a(u("Boeing-737-600"), flight_LH_1234)
+
+ # with 2 free seats
+ self.test_support.with_free_seats(2, flight_LH_1234)
+
+ # Given a passenger John Doe
+ passenger_John_Doe = self.test_support.given_a_passenger(u("John"), u("Doe"))
+
+ # Book seat for John Doe at LH-1234
+ operationStatus_John_Doe_LH_1234 = self.test_support.book_seat_for(u("John"), u("Doe"), u("LH-1234"))
+
+ # Assume a valid ticket is issued
+ self.test_support.assume_valid_ticket(operationStatus_John_Doe_LH_1234)
+
+ # Given a passenger Jane Doe
+ passenger_Jane_Doe = self.test_support.given_a_passenger(u("Jane"), u("Doe"))
+
+ # Book seat for Jane Doe at LH-1234
+ operationStatus_Jane_Doe_LH_1234 = self.test_support.book_seat_for(u("Jane"), u("Doe"), u("LH-1234"))
+
+ # Assume a valid ticket is issued
+ self.test_support.assume_valid_ticket(operationStatus_Jane_Doe_LH_1234)
+
+ # Given a passenger Jim Doe
+ passenger_Jim_Doe = self.test_support.given_a_passenger(u("Jim"), u("Doe"))
+
+ # Book seat for Jim Doe at LH-1234
+ operationStatus_Jim_Doe_LH_1234 = self.test_support.book_seat_for(u("Jim"), u("Doe"), u("LH-1234"))
+
+ # Assume no valid ticket is issued
+ self.test_support.assume_no_valid_ticked_is_issued(operationStatus_Jim_Doe_LH_1234)
+
+
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
diff --git a/.svn/pristine/03/0368ff037151ba04235d1b8819766ea0f97690be.svn-base b/.svn/pristine/03/0368ff037151ba04235d1b8819766ea0f97690be.svn-base
new file mode 100644
index 0000000..1ec539c
--- /dev/null
+++ b/.svn/pristine/03/0368ff037151ba04235d1b8819766ea0f97690be.svn-base
@@ -0,0 +1,12 @@
+from service.validation.support import ValidationSupport
+class Rules(object):
+ def __init__(self, flight, passenger):
+ self.validation_support = ValidationSupport(flight, passenger)
+
+ def validate(self):
+ """
+ The code in this method is generated from: /de.devboost.natspec.example.python/service/validation/rules.natspec
+ Never change this method or any contents of this file, all local changes will we overwritten.
+ """
+
+ return self.validation_support.status
\ No newline at end of file
diff --git a/.svn/pristine/0f/0f7f11a494b89b1134d2041d551789c4ebae09d3.svn-base b/.svn/pristine/0f/0f7f11a494b89b1134d2041d551789c4ebae09d3.svn-base
new file mode 100644
index 0000000..10705ba
--- /dev/null
+++ b/.svn/pristine/0f/0f7f11a494b89b1134d2041d551789c4ebae09d3.svn-base
@@ -0,0 +1,18 @@
+Given an airplane Boeing-737-600
+
+Given a flight LH-1234
+ that is executed using a Boeing-737-600
+ With 2 free seats
+
+Given a passenger John Doe
+
+// first passenger
+Book seat for John Doe at LH-1234
+ Assume a valid ticket is issued
+
+// cancel first passenger
+Cancel seat for John Doe at LH-1234
+ Assume a valid ticket is issued
+
+Cancel seat for John Doe at LH-1234
+ Assume no valid ticket is issued
diff --git a/.svn/pristine/2f/2fbb15a700985245d3f91083b73c0e33c16021dd.svn-base b/.svn/pristine/2f/2fbb15a700985245d3f91083b73c0e33c16021dd.svn-base
new file mode 100644
index 0000000..e2e2116
--- /dev/null
+++ b/.svn/pristine/2f/2fbb15a700985245d3f91083b73c0e33c16021dd.svn-base
@@ -0,0 +1,90 @@
+class Entity(object):
+ # A global counter that holds the next available entity ID.
+ _counter = 0
+
+ def __init__(self):
+ """Creates a new entity and initialized its ID."""
+ Entity._counter += 1
+ self.id = Entity._counter
+
+
+class NamedEntity(Entity):
+ """This is a super class for all entities that carry a name."""
+ def __init__(self, name):
+ super(NamedEntity, self).__init__()
+ self.name = name
+
+
+class Passenger(Entity):
+ """A Passenger object represents a person who can be booked on flights."""
+
+ def __init__(self, first_name, last_name):
+ """Creates a new passenger with the given first and last name, having an initial ago of zero.
+ :param firstname: the first name of the passenger.
+ :param lastname: the last name of the passenger.
+ """
+ super(Passenger, self).__init__()
+ self.first_name = first_name
+ self.last_name = last_name
+ self.age = 0
+
+class Flight(NamedEntity):
+ """A Flight represents the opportunity to travel from one airport to another.
+ Each Flight is executed using a particular type of airplane and holds a limited amount of passengers.
+ """
+
+ def __init__(self, name):
+ """Creates a new flight with the given name.
+ :param name: the new name for the flight.
+ """
+ super(Flight, self).__init__(name)
+ self.__airplane = None
+ self.passenger_ids = []
+ self.__free_seats = 0
+
+ @property
+ def airplane(self):
+ return self._airplane
+
+ @airplane.setter
+ def airplane(self, value):
+ self.__airplane = value
+ self.__free_seats = value.total_seats
+
+ @property
+ def free_seats(self):
+ return self.__free_seats - len(self.passenger_ids)
+
+ @free_seats.setter
+ def free_seats(self, value):
+ self.__free_seats = value
+
+ def has_passenger(self, passenger):
+ return passenger.id in self.passenger_ids
+
+ def add_passenger(self, passenger):
+ self.passenger_ids.append(passenger.id)
+
+ def remove_passenger(self, passenger):
+ if passenger.id in self.passenger_ids:
+ self.passenger_ids.remove(passenger.id)
+ return True
+ return False
+
+
+class AirplaneType(NamedEntity):
+ """An AirplaneType represents a specific typo of airplane which is
+ characterized by its name and a number of total seats.
+ """
+
+ def __init__(self, name):
+ """Creates a new AirplaneType entity with the given name.
+ :param name: the name of the type of airplane.
+ """
+ super(AirplaneType, self).__init__(name)
+ self.total_seats = 0
+
+
+
+
+
diff --git a/.svn/pristine/30/302576028730c94a129ddb37be9c8a0d12e97668.svn-base b/.svn/pristine/30/302576028730c94a129ddb37be9c8a0d12e97668.svn-base
new file mode 100644
index 0000000..3aaad00
--- /dev/null
+++ b/.svn/pristine/30/302576028730c94a129ddb37be9c8a0d12e97668.svn-base
@@ -0,0 +1,141 @@
+from natspec_utils.decorators import TextSyntax
+
+
+class TestSupport(object):
+ """This class contains all test support methods that are required to make the
+ example specifications executable. Methods that are decorated with the
+ TextSyntax decorator are recognized by NatSpec.
+ This class is parameterized by two parameters that are passed to the
+ constructor (the service class which implements the business logic and the
+ entity manager that provides access to all entities).
+ """
+
+ def __init__(self, service, persistence_context, test_case):
+ """Creates a new {@link TestSupport} instance. This constructor is usually
+ invoked from a {@link _NatSpecTemplate}.
+ :param service: the business service logic.
+ :param persistence_context: the entity manager to access entities.
+ :param test_case: the test case we are running, needed to access asserts
+ """
+ self.service = service
+ self.persistence_context = persistence_context
+ self.test_case = test_case
+ self.passengers = {}
+ self.flights = {}
+ self.airplane_types = {}
+
+ @TextSyntax(["Given a Passenger #1 #2"], types=["str", "str"], return_type="Passenger")
+ def given_a_passenger(self, first_name, last_name):
+ """Creates a new passenger.
+ :param first_name: the first name of the passenger.
+ :param last_name: the last name of the passenger.
+ :returns: the newly created passenger.
+ """
+ passenger = self.persistence_context.create_passenger(first_name, last_name)
+ self.passengers.update({"{0} {1}".format(first_name, last_name): passenger})
+ return passenger
+
+ @TextSyntax("With age of #2 years", types=["Passenger", "int"])
+ def with_age_of_years(self, passenger, age):
+ """Sets the age of the given passenger. The passenger is expected to be
+ contained in the implicit context (i.e., it must be created by a previous
+ sentence/test support method). The name of the passenger is not
+ explicitly required here, because there is no placeholder for the
+ passenger parameter (i.e., #1 is missing).
+ :param passenger: the passenger to set the age for.
+ :param age: the new age for the passenger.
+ """
+ passenger.age = age
+
+ @TextSyntax(["Given an Airplane #1"], types=["str"], return_type="AirplaneType")
+ def given_an_airplane(self, name):
+ """Creates a new type of airplane.
+ :param name: the name of the type of airplane.
+ :returns: the newly created airplane type.
+ """
+ airplane_type = self.persistence_context.create_airplane_type(name)
+ self.airplane_types.update({name: airplane_type})
+ return airplane_type
+
+ @TextSyntax(["Given a flight #1"], types=["str", ], return_type="Flight")
+ def given_a_flight(self, name):
+ """Creates a new flight.
+ :param name: the name of the flight.
+ :returns: the newly created flight.
+ """
+ flight = self.persistence_context.create_flight(name)
+ self.flights.update({name: flight})
+ return flight
+
+ @TextSyntax("that is executed using a #1", types=["str", "Flight"])
+ def that_is_executed_using_a(self, airplane_name, flight):
+ """Assigns the type of airplane that is used to execute the last mentioned flight.
+ :param airplane_name: the type of airplane to assign to the flight.
+ :param flight: the flight for which to set the airplane type (must be available from context).
+ """
+ airplane = self.airplane_types.get(airplane_name)
+ flight.airplane = airplane
+
+ @TextSyntax("With #1 free seats", types=["int", "Flight"])
+ def with_free_seats(self, free_seats, flight):
+ """Sets the number of free seats for the flight mentioned last.
+ :param free_seats: the number of free seats
+ :param flight: the flight to set the seats for (must be available from context).
+ """
+ flight.free_seats = free_seats
+
+ @TextSyntax("Book seat for #1 #2 at #3", types=["str", "str", "str"], return_type="OperationStatus")
+ def book_seat_for(self, first_name, last_name, flight_name):
+ """Tries to book a seat for the given passenger on the given flight.
+ :param first_name: the first name of passenger to book the flight for
+ :param last_name: the last name of passenger to book the flight for
+ :param flight_name: the name of flight to book the seat on.
+ :returns: the status of the booking operation which can be validated using
+ assume_valid_ticket(OperationStatus) or
+ assume_no_valid_ticked_is_issued(OperationStatus).
+ """
+ passenger = self.passengers.get("{0} {1}".format(first_name, last_name))
+ flight = self.flights.get(flight_name)
+ return self.service.book_seat(passenger, flight)
+
+ @TextSyntax("Cancel seat for #1 #2 at #3", types=["str", "str", "str"], return_type="OperationStatus")
+ def cancel_seat_for(self, first_name, last_name, flight_name):
+ """Tries to cancel the given passenger on the given flight.
+ :param first_name: the first name of passenger to book the flight for
+ :param last_name: the last name of passenger to book the flight for
+ :param flight_name: the name of flight to book the seat on.
+ :returns: the status of the cancel operation which can be validated using
+ assume_valid_ticket(OperationStatus) or
+ assume_no_valid_ticked_is_issued(OperationStatus).
+ """
+ passenger = self.passengers.get("{0} {1}".format(first_name, last_name))
+ flight = self.flights.get("{0}".format(flight_name))
+ return self.service.cancel_seat(passenger, flight)
+
+ @TextSyntax(["Assume a valid ticket is issued", "Assume cancellation successful"], types=["OperationStatus"])
+ def assume_valid_ticket(self, status):
+ """Checks that the validity of the last operation is True
+ (i.e., that the operation was successful). This method has a TextSyntax decorator
+ with multiple patterns (first arg) to map multiple sentences to this method.
+ :param status: the status of the last operation (must be implicitly available from context).
+ """
+ self.test_case.assertTrue(status.valid, msg=status.msg)
+
+ @TextSyntax("Assume no valid ticket is issued", types=["OperationStatus"])
+ def assume_no_valid_ticked_is_issued(self, status):
+ """Checks that the validity of the last executed business operations is False.
+ :param status: the status of the last operation (implicit parameter, not explicitly mentioned in sentence)
+ """
+ self.test_case.assertFalse(status.valid, msg=status.msg)
+
+
+ @TextSyntax("Assume #1 has passenger #2", types=["Flight", "Passenger"])
+ def assume_has_passenger(self, flight, passenger):
+ """Checks that the given passenger is booked for the given flight. Both the
+ flight and the passenger must be referenced explicitly.
+ :param flight: the flight to check
+ :param passenger: the passenger to check
+ """
+ self.test_case.assertTrue(flight.has_passenger(passenger))
+
+
diff --git a/.svn/pristine/39/39e0595231116a13c8ad773377313b954a3398a6.svn-base b/.svn/pristine/39/39e0595231116a13c8ad773377313b954a3398a6.svn-base
new file mode 100644
index 0000000..281acfc
--- /dev/null
+++ b/.svn/pristine/39/39e0595231116a13c8ad773377313b954a3398a6.svn-base
@@ -0,0 +1,24 @@
+Given an airplane Boeing-737-600
+
+Given a flight LH-1234
+ that is executed using a Boeing-737-600
+ With 1 free seats
+
+Given a passenger John Doe
+Given a passenger Jane Mejer
+
+// first passenger
+Book seat for John Doe at LH-1234
+ Assume a valid ticket is issued
+
+// second passenger
+Book seat for Jane Mejer at LH-1234
+ Assume no valid ticket is issued
+
+// cancel first passenger
+Cancel seat for John Doe at LH-1234
+ Assume cancellation successful
+
+// rebook second passenger on now free set
+Book seat for Jane Mejer at LH-1234
+ Assume a valid ticket is issued
diff --git a/.svn/pristine/3d/3d7bada97b45c25e921639fc40f1fc1538de0da4.svn-base b/.svn/pristine/3d/3d7bada97b45c25e921639fc40f1fc1538de0da4.svn-base
new file mode 100644
index 0000000..07cdabd
--- /dev/null
+++ b/.svn/pristine/3d/3d7bada97b45c25e921639fc40f1fc1538de0da4.svn-base
@@ -0,0 +1,20 @@
+import unittest
+from test.support import TestSupport
+from service.airline_service import AirlineService
+from persistence.in_memory_context import InMemoryPersistenceContext
+
+class BookSeatTwice(unittest.TestCase):
+ def setUp(self):
+ self.service = AirlineService()
+ self.persistence_context = InMemoryPersistenceContext()
+ self.test_support = TestSupport(self.service, self.persistence_context, self)
+
+ def test(self):
+ """
+ The code in this method is generated from: /de.devboost.natspec.example.python/test/scenarios/book_seat_twice.natspec
+ Never change this method or any contents of this file, all local changes will we overwritten.
+ """
+
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
diff --git a/.svn/pristine/3f/3f651f40a18a93d31f75935b1fa0d69dd9608656.svn-base b/.svn/pristine/3f/3f651f40a18a93d31f75935b1fa0d69dd9608656.svn-base
new file mode 100644
index 0000000..94e5727
--- /dev/null
+++ b/.svn/pristine/3f/3f651f40a18a93d31f75935b1fa0d69dd9608656.svn-base
@@ -0,0 +1,4 @@
+class OperationStatus(object):
+ def __init__(self, msg="", status=True):
+ self.msg = msg
+ self.valid = status
\ No newline at end of file
diff --git a/.svn/pristine/4b/4b4f209134389ee2ddbfedbd05fa6026986b7510.svn-base b/.svn/pristine/4b/4b4f209134389ee2ddbfedbd05fa6026986b7510.svn-base
new file mode 100644
index 0000000..30a3a43
--- /dev/null
+++ b/.svn/pristine/4b/4b4f209134389ee2ddbfedbd05fa6026986b7510.svn-base
@@ -0,0 +1,20 @@
+import unittest
+from test.support import TestSupport
+from service.airline_service import AirlineService
+from persistence.in_memory_context import InMemoryPersistenceContext
+
+class OverbookSeatNumber(unittest.TestCase):
+ def setUp(self):
+ self.service = AirlineService()
+ self.persistence_context = InMemoryPersistenceContext()
+ self.test_support = TestSupport(self.service, self.persistence_context, self)
+
+ def test(self):
+ """
+ The code in this method is generated from: /de.devboost.natspec.example.python/test/scenarios/overbook_seat_number.natspec
+ Never change this method or any contents of this file, all local changes will we overwritten.
+ """
+
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
diff --git a/.svn/pristine/4b/4b5d919f5509e01c2663f0b5df8ec8261cfffe8f.svn-base b/.svn/pristine/4b/4b5d919f5509e01c2663f0b5df8ec8261cfffe8f.svn-base
new file mode 100644
index 0000000..ba848a1
--- /dev/null
+++ b/.svn/pristine/4b/4b5d919f5509e01c2663f0b5df8ec8261cfffe8f.svn-base
@@ -0,0 +1,13 @@
+// This scenario describes a simple booking process
+// for an exemplary passenger
+
+Given a Passenger John Doe
+Given an Airplane Boeing-787
+
+Given a flight LH-1234
+ that is executed using a Boeing-787
+ With 200 free seats
+
+Book seat for John Doe at LH-1234
+
+Assume a valid ticket is issued
\ No newline at end of file
diff --git a/.svn/pristine/4b/4b84ab3d95ee9b3b61da4a406b7cabd80aab8a38.svn-base b/.svn/pristine/4b/4b84ab3d95ee9b3b61da4a406b7cabd80aab8a38.svn-base
new file mode 100644
index 0000000..94a56ba
--- /dev/null
+++ b/.svn/pristine/4b/4b84ab3d95ee9b3b61da4a406b7cabd80aab8a38.svn-base
@@ -0,0 +1,9 @@
+class OperationStatus(object):
+ """Objects of type OperationStatus are used to capture the result of
+ business operations. Each result comprises of a message and a validity flag
+ which indicates success or failure of the operation.
+ """
+
+ def __init__(self, msg="", status=True):
+ self.msg = msg
+ self.valid = status
\ No newline at end of file
diff --git a/.svn/pristine/4b/4bb03f9d7db8d78616acee473d010dedca0d96a8.svn-base b/.svn/pristine/4b/4bb03f9d7db8d78616acee473d010dedca0d96a8.svn-base
new file mode 100644
index 0000000..0dd91d2
--- /dev/null
+++ b/.svn/pristine/4b/4bb03f9d7db8d78616acee473d010dedca0d96a8.svn-base
@@ -0,0 +1,70 @@
+class Entity(object):
+ # A global counter that holds the next available entity ID.
+ _counter = 0
+
+ def __init__(self):
+ """Creates a new entity and initialized its ID."""
+ Entity._counter += 1
+ self.id = Entity._counter
+
+
+class NamedEntity(Entity):
+ def __init__(self, name):
+ super(NamedEntity, self).__init__()
+ self.name = name
+
+
+class Passenger(Entity):
+ def __init__(self, first_name, last_name):
+ super(Passenger, self).__init__()
+ self.first_name = first_name
+ self.last_name = last_name
+ self.age = 0
+
+class Flight(NamedEntity):
+ def __init__(self, name):
+ super(Flight, self).__init__(name)
+
+ self.__airplane = None
+ self.passenger_ids = []
+ self.__free_seats = 0
+
+ @property
+ def airplane(self):
+ return self._airplane
+
+ @airplane.setter
+ def airplane(self, value):
+ self.__airplane = value
+ self.__free_seats = value.total_seats
+
+ @property
+ def free_seats(self):
+ return self.__free_seats - len(self.passenger_ids)
+
+ @free_seats.setter
+ def free_seats(self, value):
+ self.__free_seats = value
+
+ def has_passenger(self, passenger):
+ return passenger.id in self.passenger_ids
+
+ def add_passenger(self, passenger):
+ self.passenger_ids.append(passenger.id)
+
+ def remove_passenger(self, passenger):
+ if passenger.id in self.passenger_ids:
+ self.passenger_ids.remove(passenger.id)
+ return True
+ return False
+
+
+class AirplaneType(NamedEntity):
+ def __init__(self, name):
+ super(AirplaneType, self).__init__(name)
+ self.total_seats = 0
+
+
+
+
+
diff --git a/.svn/pristine/5a/5a9ed3df9efef9fae82bde66b113ae8d124f08c7.svn-base b/.svn/pristine/5a/5a9ed3df9efef9fae82bde66b113ae8d124f08c7.svn-base
new file mode 100644
index 0000000..d46941c
--- /dev/null
+++ b/.svn/pristine/5a/5a9ed3df9efef9fae82bde66b113ae8d124f08c7.svn-base
@@ -0,0 +1,20 @@
+import unittest
+from test.support import TestSupport
+from service.airline_service import AirlineService
+from persistence.in_memory_context import InMemoryPersistenceContext
+
+class CancelAndRebookSeat(unittest.TestCase):
+ def setUp(self):
+ self.service = AirlineService()
+ self.persistence_context = InMemoryPersistenceContext()
+ self.test_support = TestSupport(self.service, self.persistence_context, self)
+
+ def test(self):
+ """
+ The code in this method is generated from: /de.devboost.natspec.example.python/test/scenarios/cancel_and_rebook_seat.natspec
+ Never change this method or any contents of this file, all local changes will we overwritten.
+ """
+
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
diff --git a/.svn/pristine/5d/5daf54df2af2ae4db398e3e9a6c99b80344db878.svn-base b/.svn/pristine/5d/5daf54df2af2ae4db398e3e9a6c99b80344db878.svn-base
new file mode 100644
index 0000000..578cbcd
--- /dev/null
+++ b/.svn/pristine/5d/5daf54df2af2ae4db398e3e9a6c99b80344db878.svn-base
@@ -0,0 +1,36 @@
+from service.validation.rules import Rules
+from service.status import OperationStatus
+
+class AirlineService(object):
+ """The AirlineService provides very basic business functionality for the
+ airline domain. It allows to book seats for passengers on flights
+ and to cancel these seats.
+ """
+
+ def book_seat(self, passenger, flight):
+ """Tries to book a seat for the given passenger on the given flight. Before
+ the seat is actually booked some validation rules are checked to make
+ sure the constraints of the domain (e.g., that a passenger can book at
+ most one seat for a flight) are met. If one of the validation rules is
+ violated, this operation fails.
+ :param flight: the flight to book the seat on.
+ :param passenger: the passenger to book the seat for.
+ :returns: a status object representing the operations success (or failure).
+ """
+ rules = Rules(flight, passenger)
+ status = rules.validate()
+ if status.valid:
+ flight.add_passenger(passenger)
+ return status
+
+ def cancel_seat(self, passenger, flight):
+ """Cancels the seat booked by the given passenger on the given flight. This
+ operation can fail if the passenger has not booked a seat on the given
+ flight.
+ :param passenger: the passenger to cancel the seat for.
+ :param flight: the flight to cancel the seat on.
+ :returns: a status object representing the operations success (or failure).
+ """
+ if flight.remove_passenger(passenger):
+ return OperationStatus("Passenger was removed", True)
+ return OperationStatus("Passenger was not booked on flight", False)
\ No newline at end of file
diff --git a/.svn/pristine/68/685911c54598042f7d86a63507470ac8387936e3.svn-base b/.svn/pristine/68/685911c54598042f7d86a63507470ac8387936e3.svn-base
new file mode 100644
index 0000000..0635f12
--- /dev/null
+++ b/.svn/pristine/68/685911c54598042f7d86a63507470ac8387936e3.svn-base
@@ -0,0 +1,8 @@
+from service.validation.support import ValidationSupport
+class _NatSpecTemplate(object):
+ def __init__(self, flight, passenger):
+ self.validation_support = ValidationSupport(flight, passenger)
+
+ def validate(self):
+ """ @MethodBody """
+ return self.validation_support.status
\ No newline at end of file
diff --git a/.svn/pristine/6f/6f824ab29cab36565094cb899a3c69dd3504322c.svn-base b/.svn/pristine/6f/6f824ab29cab36565094cb899a3c69dd3504322c.svn-base
new file mode 100644
index 0000000..21ec919
--- /dev/null
+++ b/.svn/pristine/6f/6f824ab29cab36565094cb899a3c69dd3504322c.svn-base
@@ -0,0 +1,16 @@
+import unittest
+from test.support import TestSupport
+from service.airline_service import AirlineService
+from persistence.in_memory_context import InMemoryPersistenceContext
+
+class _NatSpecTemplate(unittest.TestCase):
+ def setUp(self):
+ self.service = AirlineService()
+ self.persistence_context = InMemoryPersistenceContext()
+ self.test_support = TestSupport(self.service, self.persistence_context, self)
+
+ def test(self):
+ """ @MethodBody """
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
diff --git a/.svn/pristine/70/707e2d830b9e02fe2d8959e0df52bdf20cbb8d64.svn-base b/.svn/pristine/70/707e2d830b9e02fe2d8959e0df52bdf20cbb8d64.svn-base
new file mode 100644
index 0000000..286d563
--- /dev/null
+++ b/.svn/pristine/70/707e2d830b9e02fe2d8959e0df52bdf20cbb8d64.svn-base
@@ -0,0 +1,21 @@
+import unittest
+from test.support import TestSupport
+from service.airline_service import AirlineService
+from persistence.in_memory_context import InMemoryPersistenceContext
+
+class _NatSpecTemplate(unittest.TestCase):
+ def __init__(self):
+ self.service = AirlineService()
+ self.test_support = TestSupport(self.service, self.persistence_context, self)
+ self.persistence_context = InMemoryPersistenceContext()
+
+ def setUp(self):
+ self.service = AirlineService()
+ self.persistence_context = InMemoryPersistenceContext()
+ self.test_support = TestSupport(self.service, self.persistence_context, self)
+
+ def test(self):
+ """ @MethodBody """
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
diff --git a/.svn/pristine/72/7208b39c09081a0357b727a62e00abaacbdc45a2.svn-base b/.svn/pristine/72/7208b39c09081a0357b727a62e00abaacbdc45a2.svn-base
new file mode 100644
index 0000000..3709f1c
--- /dev/null
+++ b/.svn/pristine/72/7208b39c09081a0357b727a62e00abaacbdc45a2.svn-base
@@ -0,0 +1,21 @@
+Given an airplane Boeing-737-600
+
+Given a flight LH-1234
+ that is executed using a Boeing-737-600
+ with 2 free seats
+
+Given a passenger John Doe
+
+// first passenger
+Book seat for John Doe at LH-1234
+ Assume a valid ticket is issued
+
+// second passenger
+Given a passenger Jane Doe
+ Book seat for Jane Doe at LH-1234
+ Assume a valid ticket is issued
+
+// third passenger
+Given a passenger Jim Doe
+ Book seat for Jim Doe at LH-1234
+ Assume no valid ticket is issued
\ No newline at end of file
diff --git a/.svn/pristine/73/73bd9d09363c3cab9f4a106473016a7c673abcdb.svn-base b/.svn/pristine/73/73bd9d09363c3cab9f4a106473016a7c673abcdb.svn-base
new file mode 100644
index 0000000..83f47ab
--- /dev/null
+++ b/.svn/pristine/73/73bd9d09363c3cab9f4a106473016a7c673abcdb.svn-base
@@ -0,0 +1,16 @@
+from service.validation.rules import Rules
+from service.status import OperationStatus
+
+
+class AirlineService(object):
+ def book_seat(self, passenger, flight):
+ rules = Rules(flight, passenger)
+ status = rules.validate()
+ if status.valid:
+ flight.add_passenger(passenger)
+ return status
+
+ def cancel_seat(self, passenger, flight):
+ if flight.remove_passenger(passenger):
+ return OperationStatus("Passenger was removed", True)
+ return OperationStatus("Passenger was not booked on flight", False)
\ No newline at end of file
diff --git a/.svn/pristine/81/8171a7d6c01a1ddc0f28a722612e19d785ce13b3.svn-base b/.svn/pristine/81/8171a7d6c01a1ddc0f28a722612e19d785ce13b3.svn-base
new file mode 100644
index 0000000..616350a
--- /dev/null
+++ b/.svn/pristine/81/8171a7d6c01a1ddc0f28a722612e19d785ce13b3.svn-base
@@ -0,0 +1,54 @@
+from natspec_utils.stringutils import stringToUnicode as u;
+
+import unittest
+from test.support import TestSupport
+from service.airline_service import AirlineService
+from persistence.in_memory_context import InMemoryPersistenceContext
+
+class BookSeatTwice(unittest.TestCase):
+ def __init__(self):
+ self.service = AirlineService()
+ self.test_support = TestSupport(self.service, self.persistence_context, self)
+ self.persistence_context = InMemoryPersistenceContext()
+
+ def setUp(self):
+ self.service = AirlineService()
+ self.persistence_context = InMemoryPersistenceContext()
+ self.test_support = TestSupport(self.service, self.persistence_context, self)
+
+ def test(self):
+ """
+ The code in this method is generated from: /de.devboost.natspec.example.python/test/scenarios/book_seat_twice.natspec
+ Never change this method or any contents of this file, all local changes will we overwritten.
+ """
+ # Given a Passenger John Doe
+ passenger_John_Doe = self.test_support.given_a_passenger(u("John"), u("Doe"))
+
+ # Given an Airplane Boeing-787
+ airplaneType_Boeing_787 = self.test_support.given_an_airplane(u("Boeing-787"))
+
+ # Given a flight LH-1234
+ flight_LH_1234 = self.test_support.given_a_flight(u("LH-1234"), airplaneType_Boeing_787)
+
+ # that is executed using a Boeing-787
+ self.test_support.that_is_executed_using_a(u("Boeing-787"), flight_LH_1234)
+
+ # With 200 free seats
+ self.test_support.with_free_seats(200, flight_LH_1234)
+
+ # Book seat for John Doe at LH-1234
+ operationStatus_John_Doe_LH_1234 = self.test_support.book_seat_for(u("John"), u("Doe"), u("LH-1234"))
+
+ # Assume a valid ticket is issued
+ self.test_support.assume_valid_ticket(operationStatus_John_Doe_LH_1234)
+
+ # Book seat for John Doe at LH-1234
+ operationStatus_John_Doe_LH_12340 = self.test_support.book_seat_for(u("John"), u("Doe"), u("LH-1234"))
+
+ # Assume no valid ticket is issued
+ self.test_support.assume_no_valid_ticked_is_issued(operationStatus_John_Doe_LH_12340)
+
+
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
diff --git a/.svn/pristine/85/85b1b1241cd7d08aeaec1d8cec75db99585e6de8.svn-base b/.svn/pristine/85/85b1b1241cd7d08aeaec1d8cec75db99585e6de8.svn-base
new file mode 100644
index 0000000..2478004
--- /dev/null
+++ b/.svn/pristine/85/85b1b1241cd7d08aeaec1d8cec75db99585e6de8.svn-base
@@ -0,0 +1,15 @@
+// This scenario describes an erroneous booking example
+// where the same passenger is booked twice for one flight
+
+Given a Passenger John Doe
+Given an Airplane Boeing-787
+Given a flight LH-1234
+ that is executed using a Boeing-787
+ With 200 free seats
+
+Book seat for John Doe at LH-1234
+ Assume a valid ticket is issued
+
+// Second booking for the same passenger should fail
+Book seat for John Doe at LH-1234
+ Assume no valid ticket is issued
\ No newline at end of file
diff --git a/.svn/pristine/93/93cf9800571991cd4c985b63962c9663e52aa916.svn-base b/.svn/pristine/93/93cf9800571991cd4c985b63962c9663e52aa916.svn-base
new file mode 100644
index 0000000..cc018d6
--- /dev/null
+++ b/.svn/pristine/93/93cf9800571991cd4c985b63962c9663e52aa916.svn-base
@@ -0,0 +1,33 @@
+from service.status import OperationStatus
+from natspec_utils.decorators import TextSyntax
+class ValidationSupport():
+ def __init__(self, flight, passenger):
+ self.flight = flight
+ self.passenger = passenger
+ self.status = OperationStatus()
+
+ def set_invalid(self, msg):
+ self.status.valid = False
+ self.status.msg = msg
+
+ @TextSyntax("Each Passenger can only be booked once.")
+ def check_unique_passenger(self):
+ if self.passenger.id in self.flight.passenger_ids:
+ self.set_invalid("A passenger can only be booked once for each flight.")
+
+ @TextSyntax("There should be at least #1 free seats to handle overbooking.", types=["int"])
+ def check_free_seats_with_buffer(self, overbooking_buffer):
+ if self.flight.free_seats < overbooking_buffer:
+ self.set_invalid("There are no free seats for the flight.")
+
+ @TextSyntax("There needs to be a free seat for the passenger.")
+ def check_free_seats(self):
+ if self.flight.free_seats < 1:
+ self.set_invalid("There are no free seats for the flight.")
+
+ @TextSyntax("The Passenger needs to be at least #1 years old.", types=["int"])
+ def passenger_needs_to_be_at_least_years_old(self, minimal_age):
+ if self.passenger.age < minimal_age:
+ self.set_invalid("The passenger needs to be at least {0} years.".format(minimal_age))
+
+
diff --git a/.svn/pristine/9c/9cd1742dad5745fa11d674aa2f20dbc44bced1d1.svn-base b/.svn/pristine/9c/9cd1742dad5745fa11d674aa2f20dbc44bced1d1.svn-base
new file mode 100644
index 0000000..06940f6
--- /dev/null
+++ b/.svn/pristine/9c/9cd1742dad5745fa11d674aa2f20dbc44bced1d1.svn-base
@@ -0,0 +1,27 @@
+import unittest
+from test.support import TestSupport
+from service.airline_service import AirlineService
+from persistence.in_memory_context import InMemoryPersistenceContext
+
+class _NatSpecTemplate(unittest.TestCase):
+ """This class serves as a template for all classes that are generated for
+ NatSpec scenarios (.natspec files). It is recognized by NatSpec based on its
+ special name and applies to all scenarios in the same package and all sub
+ packages (unless there is another template class in one of the sub packages).
+ This particular template is a unittest test case where the concrete steps of the
+ test are filled by the NatSpec code generator.
+ """
+
+ def setUp(self):
+ """Sets up the test environment (i.e., initialize the service class, the
+ entity manager and the test support class).
+ """
+ self.service = AirlineService()
+ self.persistence_context = InMemoryPersistenceContext()
+ self.test_support = TestSupport(self.service, self.persistence_context, self)
+
+ def test(self):
+ """ @MethodBody """
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
diff --git a/.svn/pristine/a7/a7f43475f12c2bfd6a4ebbd04fdafe92535cd97c.svn-base b/.svn/pristine/a7/a7f43475f12c2bfd6a4ebbd04fdafe92535cd97c.svn-base
new file mode 100644
index 0000000..4f359fd
--- /dev/null
+++ b/.svn/pristine/a7/a7f43475f12c2bfd6a4ebbd04fdafe92535cd97c.svn-base
@@ -0,0 +1,50 @@
+from service.status import OperationStatus
+from natspec_utils.decorators import TextSyntax
+class ValidationSupport():
+ """The ValidationSupport call defined all methods that are required to
+ execute the textual validation rules present in this example.
+ """
+
+ def __init__(self, flight, passenger):
+ """Creates a new instance of this class that can be used to validate the
+ given flight and passenger.
+
+ :param flight: the flight to validate.
+ :param passenger: the passenger to validate.
+ """
+ self.flight = flight
+ self.passenger = passenger
+ self.status = OperationStatus()
+
+ def set_invalid(self, msg):
+ """Sets the status of this validation to invalid (failure) and adds the given message.
+ :param msg: the message to add.
+ """
+ self.status.valid = False
+ self.status.msg = msg
+
+ @TextSyntax("Each Passenger can only be booked once.")
+ def check_unique_passenger(self):
+ """Checks that the passenger has not already booked a seat on this flight."""
+ if self.passenger.id in self.flight.passenger_ids:
+ self.set_invalid("A passenger can only be booked once for each flight.")
+
+ @TextSyntax("There should be at least #1 free seats to handle overbooking.", types=["int"])
+ def check_free_seats_with_buffer(self, overbooking_buffer):
+ """Checks that the given number of seats is held free."""
+ if self.flight.free_seats < overbooking_buffer:
+ self.set_invalid("There are no free seats for the flight.")
+
+ @TextSyntax("There needs to be a free seat for the passenger.")
+ def check_free_seats(self):
+ """Checks that there is at least one seat available."""
+ if self.flight.free_seats < 1:
+ self.set_invalid("There are no free seats for the flight.")
+
+ @TextSyntax("The Passenger needs to be at least #1 years old.", types=["int"])
+ def passenger_needs_to_be_at_least_years_old(self, minimal_age):
+ """Checks that the passenger has at least the given age (in years)."""
+ if self.passenger.age < minimal_age:
+ self.set_invalid("The passenger needs to be at least {0} years.".format(minimal_age))
+
+
diff --git a/.svn/pristine/b0/b0a58c3d3226003bdca1cfd8fe36e5057a176e83.svn-base b/.svn/pristine/b0/b0a58c3d3226003bdca1cfd8fe36e5057a176e83.svn-base
new file mode 100644
index 0000000..3b42876
--- /dev/null
+++ b/.svn/pristine/b0/b0a58c3d3226003bdca1cfd8fe36e5057a176e83.svn-base
@@ -0,0 +1,19 @@
+from service.validation.support import ValidationSupport
+
+class _NatSpecTemplate(object):
+ """This class serves as a template for validation rule classes that are written
+ in plain natural language. The template is instantiated by NatSpec for all
+ the .natspec files in this package. The @MethodBody placeholder
+ in validate() is replaced with the code that performs the actual validation.
+ See class Rules for a concrete example validation class.
+ This class is an example of applying NatSpec for non-testing purposes.
+ """
+ def __init__(self, flight, passenger):
+ self.validation_support = ValidationSupport(flight, passenger)
+
+ def validate(self):
+ """Checks that all validation rules are met.
+ :returns: the status of the validation (i.e., success or failure).
+ """
+ """ @MethodBody """
+ return self.validation_support.status
\ No newline at end of file
diff --git a/.svn/pristine/b6/b6aa00adf118dc7b6e042537b3bc565b0cabd105.svn-base b/.svn/pristine/b6/b6aa00adf118dc7b6e042537b3bc565b0cabd105.svn-base
new file mode 100644
index 0000000..b561c84
--- /dev/null
+++ b/.svn/pristine/b6/b6aa00adf118dc7b6e042537b3bc565b0cabd105.svn-base
@@ -0,0 +1 @@
+natspec_utils
diff --git a/.svn/pristine/bb/bbedbb12b4dba55e7aa757e69c73197b33242279.svn-base b/.svn/pristine/bb/bbedbb12b4dba55e7aa757e69c73197b33242279.svn-base
new file mode 100644
index 0000000..3e563bd
--- /dev/null
+++ b/.svn/pristine/bb/bbedbb12b4dba55e7aa757e69c73197b33242279.svn-base
@@ -0,0 +1,66 @@
+from natspec_utils.stringutils import stringToUnicode as u;
+
+import unittest
+from test.support import TestSupport
+from service.airline_service import AirlineService
+from persistence.in_memory_context import InMemoryPersistenceContext
+
+class OverbookSeatNumber(unittest.TestCase):
+ def __init__(self):
+ self.service = AirlineService()
+ self.test_support = TestSupport(self.service, self.persistence_context, self)
+ self.persistence_context = InMemoryPersistenceContext()
+
+ def setUp(self):
+ self.service = AirlineService()
+ self.persistence_context = InMemoryPersistenceContext()
+ self.test_support = TestSupport(self.service, self.persistence_context, self)
+
+ def test(self):
+ """
+ The code in this method is generated from: /de.devboost.natspec.example.python/test/scenarios/overbook_seat_number.natspec
+ Never change this method or any contents of this file, all local changes will we overwritten.
+ """
+ # Given an airplane Boeing-737-600
+ airplaneType_Boeing_737_600 = self.test_support.given_an_airplane(u("Boeing-737-600"))
+
+ # Given a flight LH-1234
+ flight_LH_1234 = self.test_support.given_a_flight(u("LH-1234"), airplaneType_Boeing_737_600)
+
+ # that is executed using a Boeing-737-600
+ self.test_support.that_is_executed_using_a(u("Boeing-737-600"), flight_LH_1234)
+
+ # with 2 free seats
+ self.test_support.with_free_seats(2, flight_LH_1234)
+
+ # Given a passenger John Doe
+ passenger_John_Doe = self.test_support.given_a_passenger(u("John"), u("Doe"))
+
+ # Book seat for John Doe at LH-1234
+ operationStatus_John_Doe_LH_1234 = self.test_support.book_seat_for(u("John"), u("Doe"), u("LH-1234"))
+
+ # Assume a valid ticket is issued
+ self.test_support.assume_valid_ticket(operationStatus_John_Doe_LH_1234)
+
+ # Given a passenger Jane Doe
+ passenger_Jane_Doe = self.test_support.given_a_passenger(u("Jane"), u("Doe"))
+
+ # Book seat for Jane Doe at LH-1234
+ operationStatus_Jane_Doe_LH_1234 = self.test_support.book_seat_for(u("Jane"), u("Doe"), u("LH-1234"))
+
+ # Assume a valid ticket is issued
+ self.test_support.assume_valid_ticket(operationStatus_Jane_Doe_LH_1234)
+
+ # Given a passenger Jim Doe
+ passenger_Jim_Doe = self.test_support.given_a_passenger(u("Jim"), u("Doe"))
+
+ # Book seat for Jim Doe at LH-1234
+ operationStatus_Jim_Doe_LH_1234 = self.test_support.book_seat_for(u("Jim"), u("Doe"), u("LH-1234"))
+
+ # Assume no valid ticket is issued
+ self.test_support.assume_no_valid_ticked_is_issued(operationStatus_Jim_Doe_LH_1234)
+
+
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
diff --git a/.svn/pristine/bf/bff463ed06e3bdc23a2570854f65cee858ad783a.svn-base b/.svn/pristine/bf/bff463ed06e3bdc23a2570854f65cee858ad783a.svn-base
new file mode 100644
index 0000000..60010c6
--- /dev/null
+++ b/.svn/pristine/bf/bff463ed06e3bdc23a2570854f65cee858ad783a.svn-base
@@ -0,0 +1,54 @@
+from natspec_utils.stringutils import stringToUnicode as u;
+
+import unittest
+from test.support import TestSupport
+from service.airline_service import AirlineService
+from persistence.in_memory_context import InMemoryPersistenceContext
+
+class BookSeat(unittest.TestCase):
+ """This class serves as a template for all classes that are generated for
+ NatSpec scenarios (.natspec files). It is recognized by NatSpec based on its
+ special name and applies to all scenarios in the same package and all sub
+ packages (unless there is another template class in one of the sub packages).
+ This particular template is a unittest test case where the concrete steps of the
+ test are filled by the NatSpec code generator.
+ """
+
+ def setUp(self):
+ """Sets up the test environment (i.e., initialize the service class, the
+ entity manager and the test support class).
+ """
+ self.service = AirlineService()
+ self.persistence_context = InMemoryPersistenceContext()
+ self.test_support = TestSupport(self.service, self.persistence_context, self)
+
+ def test(self):
+ """
+ The code in this method is generated from: /de.devboost.natspec.example.python/test/scenarios/book_seat.natspec
+ Never change this method or any contents of this file, all local changes will we overwritten.
+ """
+ # Given a Passenger John Doe
+ passenger_John_Doe = self.test_support.given_a_passenger(u("John"), u("Doe"))
+
+ # Given an Airplane Boeing-787
+ airplaneType_Boeing_787 = self.test_support.given_an_airplane(u("Boeing-787"))
+
+ # Given a flight LH-1234
+ flight_LH_1234 = self.test_support.given_a_flight(u("LH-1234"))
+
+ # that is executed using a Boeing-787
+ self.test_support.that_is_executed_using_a(u("Boeing-787"), flight_LH_1234)
+
+ # With 200 free seats
+ self.test_support.with_free_seats(200, flight_LH_1234)
+
+ # Book seat for John Doe at LH-1234
+ operationStatus_John_Doe_LH_1234 = self.test_support.book_seat_for(u("John"), u("Doe"), u("LH-1234"))
+
+ # Assume a valid ticket is issued
+ self.test_support.assume_valid_ticket(operationStatus_John_Doe_LH_1234)
+
+
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
diff --git a/.svn/pristine/c6/c6a51e8753a3c623c95586e376576606831c7f8d.svn-base b/.svn/pristine/c6/c6a51e8753a3c623c95586e376576606831c7f8d.svn-base
new file mode 100644
index 0000000..df16336
--- /dev/null
+++ b/.svn/pristine/c6/c6a51e8753a3c623c95586e376576606831c7f8d.svn-base
@@ -0,0 +1,75 @@
+from natspec_utils.stringutils import stringToUnicode as u;
+
+import unittest
+from test.support import TestSupport
+from service.airline_service import AirlineService
+from persistence.in_memory_context import InMemoryPersistenceContext
+
+class CancelAndRebookSeat(unittest.TestCase):
+ """This class serves as a template for all classes that are generated for
+ NatSpec scenarios (.natspec files). It is recognized by NatSpec based on its
+ special name and applies to all scenarios in the same package and all sub
+ packages (unless there is another template class in one of the sub packages).
+ This particular template is a unittest test case where the concrete steps of the
+ test are filled by the NatSpec code generator.
+ """
+
+ def setUp(self):
+ """Sets up the test environment (i.e., initialize the service class, the
+ entity manager and the test support class).
+ """
+ self.service = AirlineService()
+ self.persistence_context = InMemoryPersistenceContext()
+ self.test_support = TestSupport(self.service, self.persistence_context, self)
+
+ def test(self):
+ """
+ The code in this method is generated from: /de.devboost.natspec.example.python/test/scenarios/cancel_and_rebook_seat.natspec
+ Never change this method or any contents of this file, all local changes will we overwritten.
+ """
+ # Given an airplane Boeing-737-600
+ airplaneType_Boeing_737_600 = self.test_support.given_an_airplane(u("Boeing-737-600"))
+
+ # Given a flight LH-1234
+ flight_LH_1234 = self.test_support.given_a_flight(u("LH-1234"))
+
+ # that is executed using a Boeing-737-600
+ self.test_support.that_is_executed_using_a(u("Boeing-737-600"), flight_LH_1234)
+
+ # With 1 free seats
+ self.test_support.with_free_seats(1, flight_LH_1234)
+
+ # Given a passenger John Doe
+ passenger_John_Doe = self.test_support.given_a_passenger(u("John"), u("Doe"))
+
+ # Given a passenger Jane Mejer
+ passenger_Jane_Mejer = self.test_support.given_a_passenger(u("Jane"), u("Mejer"))
+
+ # Book seat for John Doe at LH-1234
+ operationStatus_John_Doe_LH_1234 = self.test_support.book_seat_for(u("John"), u("Doe"), u("LH-1234"))
+
+ # Assume a valid ticket is issued
+ self.test_support.assume_valid_ticket(operationStatus_John_Doe_LH_1234)
+
+ # Book seat for Jane Mejer at LH-1234
+ operationStatus_Jane_Mejer_LH_1234 = self.test_support.book_seat_for(u("Jane"), u("Mejer"), u("LH-1234"))
+
+ # Assume no valid ticket is issued
+ self.test_support.assume_no_valid_ticked_is_issued(operationStatus_Jane_Mejer_LH_1234)
+
+ # Cancel seat for John Doe at LH-1234
+ operationStatus_John_Doe_LH_12340 = self.test_support.cancel_seat_for(u("John"), u("Doe"), u("LH-1234"))
+
+ # Assume cancellation successful
+ self.test_support.assume_valid_ticket(operationStatus_John_Doe_LH_12340)
+
+ # Book seat for Jane Mejer at LH-1234
+ operationStatus_Jane_Mejer_LH_12340 = self.test_support.book_seat_for(u("Jane"), u("Mejer"), u("LH-1234"))
+
+ # Assume a valid ticket is issued
+ self.test_support.assume_valid_ticket(operationStatus_Jane_Mejer_LH_12340)
+
+
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
diff --git a/.svn/pristine/cb/cb257dd17bb8f12d6d222f190e9d79219b9f276d.svn-base b/.svn/pristine/cb/cb257dd17bb8f12d6d222f190e9d79219b9f276d.svn-base
new file mode 100644
index 0000000..c227b18
--- /dev/null
+++ b/.svn/pristine/cb/cb257dd17bb8f12d6d222f190e9d79219b9f276d.svn-base
@@ -0,0 +1,69 @@
+from natspec_utils.stringutils import stringToUnicode as u;
+
+import unittest
+from test.support import TestSupport
+from service.airline_service import AirlineService
+from persistence.in_memory_context import InMemoryPersistenceContext
+
+class CancelAndRebookSeat(unittest.TestCase):
+ def __init__(self):
+ self.service = AirlineService()
+ self.test_support = TestSupport(self.service, self.persistence_context, self)
+ self.persistence_context = InMemoryPersistenceContext()
+
+ def setUp(self):
+ self.service = AirlineService()
+ self.persistence_context = InMemoryPersistenceContext()
+ self.test_support = TestSupport(self.service, self.persistence_context, self)
+
+ def test(self):
+ """
+ The code in this method is generated from: /de.devboost.natspec.example.python/test/scenarios/cancel_and_rebook_seat.natspec
+ Never change this method or any contents of this file, all local changes will we overwritten.
+ """
+ # Given an airplane Boeing-737-600
+ airplaneType_Boeing_737_600 = self.test_support.given_an_airplane(u("Boeing-737-600"))
+
+ # Given a flight LH-1234
+ flight_LH_1234 = self.test_support.given_a_flight(u("LH-1234"), airplaneType_Boeing_737_600)
+
+ # that is executed using a Boeing-737-600
+ self.test_support.that_is_executed_using_a(u("Boeing-737-600"), flight_LH_1234)
+
+ # With 1 free seats
+ self.test_support.with_free_seats(1, flight_LH_1234)
+
+ # Given a passenger John Doe
+ passenger_John_Doe = self.test_support.given_a_passenger(u("John"), u("Doe"))
+
+ # Given a passenger Jane Mejer
+ passenger_Jane_Mejer = self.test_support.given_a_passenger(u("Jane"), u("Mejer"))
+
+ # Book seat for John Doe at LH-1234
+ operationStatus_John_Doe_LH_1234 = self.test_support.book_seat_for(u("John"), u("Doe"), u("LH-1234"))
+
+ # Assume a valid ticket is issued
+ self.test_support.assume_valid_ticket(operationStatus_John_Doe_LH_1234)
+
+ # Book seat for Jane Mejer at LH-1234
+ operationStatus_Jane_Mejer_LH_1234 = self.test_support.book_seat_for(u("Jane"), u("Mejer"), u("LH-1234"))
+
+ # Assume no valid ticket is issued
+ self.test_support.assume_no_valid_ticked_is_issued(operationStatus_Jane_Mejer_LH_1234)
+
+ # Cancel seat for John Doe at LH-1234
+ operationStatus_John_Doe_LH_12340 = self.test_support.cancel_seat_for(u("John"), u("Doe"), u("LH-1234"))
+
+ # Assume cancellation successful
+ self.test_support.assume_valid_ticket(operationStatus_John_Doe_LH_12340)
+
+ # Book seat for Jane Mejer at LH-1234
+ operationStatus_Jane_Mejer_LH_12340 = self.test_support.book_seat_for(u("Jane"), u("Mejer"), u("LH-1234"))
+
+ # Assume a valid ticket is issued
+ self.test_support.assume_valid_ticket(operationStatus_Jane_Mejer_LH_12340)
+
+
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
diff --git a/.svn/pristine/cd/cd19710b605b40adb9fe207705bd040b6ca276da.svn-base b/.svn/pristine/cd/cd19710b605b40adb9fe207705bd040b6ca276da.svn-base
new file mode 100644
index 0000000..347336e
--- /dev/null
+++ b/.svn/pristine/cd/cd19710b605b40adb9fe207705bd040b6ca276da.svn-base
@@ -0,0 +1,60 @@
+from natspec_utils.stringutils import stringToUnicode as u;
+
+import unittest
+from test.support import TestSupport
+from service.airline_service import AirlineService
+from persistence.in_memory_context import InMemoryPersistenceContext
+
+class CancelSeatTwice(unittest.TestCase):
+ def __init__(self):
+ self.service = AirlineService()
+ self.test_support = TestSupport(self.service, self.persistence_context, self)
+ self.persistence_context = InMemoryPersistenceContext()
+
+ def setUp(self):
+ self.service = AirlineService()
+ self.persistence_context = InMemoryPersistenceContext()
+ self.test_support = TestSupport(self.service, self.persistence_context, self)
+
+ def test(self):
+ """
+ The code in this method is generated from: /de.devboost.natspec.example.python/test/scenarios/cancel_seat_twice.natspec
+ Never change this method or any contents of this file, all local changes will we overwritten.
+ """
+ # Given an airplane Boeing-737-600
+ airplaneType_Boeing_737_600 = self.test_support.given_an_airplane(u("Boeing-737-600"))
+
+ # Given a flight LH-1234
+ flight_LH_1234 = self.test_support.given_a_flight(u("LH-1234"), airplaneType_Boeing_737_600)
+
+ # that is executed using a Boeing-737-600
+ self.test_support.that_is_executed_using_a(u("Boeing-737-600"), flight_LH_1234)
+
+ # With 2 free seats
+ self.test_support.with_free_seats(2, flight_LH_1234)
+
+ # Given a passenger John Doe
+ passenger_John_Doe = self.test_support.given_a_passenger(u("John"), u("Doe"))
+
+ # Book seat for John Doe at LH-1234
+ operationStatus_John_Doe_LH_1234 = self.test_support.book_seat_for(u("John"), u("Doe"), u("LH-1234"))
+
+ # Assume a valid ticket is issued
+ self.test_support.assume_valid_ticket(operationStatus_John_Doe_LH_1234)
+
+ # Cancel seat for John Doe at LH-1234
+ operationStatus_John_Doe_LH_12340 = self.test_support.cancel_seat_for(u("John"), u("Doe"), u("LH-1234"))
+
+ # Assume a valid ticket is issued
+ self.test_support.assume_valid_ticket(operationStatus_John_Doe_LH_12340)
+
+ # Cancel seat for John Doe at LH-1234
+ operationStatus_John_Doe_LH_12341 = self.test_support.cancel_seat_for(u("John"), u("Doe"), u("LH-1234"))
+
+ # Assume no valid ticket is issued
+ self.test_support.assume_no_valid_ticked_is_issued(operationStatus_John_Doe_LH_12341)
+
+
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
diff --git a/.svn/pristine/d0/d04643cf9d33d11f5522ec5e0f50305a9c175d3a.svn-base b/.svn/pristine/d0/d04643cf9d33d11f5522ec5e0f50305a9c175d3a.svn-base
new file mode 100644
index 0000000..af71a62
--- /dev/null
+++ b/.svn/pristine/d0/d04643cf9d33d11f5522ec5e0f50305a9c175d3a.svn-base
@@ -0,0 +1,69 @@
+from natspec_utils.decorators import TextSyntax
+
+
+class TestSupport(object):
+ def __init__(self, service, persistence_context, test_case):
+ self.service = service
+ self.persistence_context = persistence_context
+ self.test_case = test_case
+ self.passengers = {}
+ self.flights = {}
+ self.airplane_types = {}
+
+ @TextSyntax(["Given a Passenger #1 #2"], types=["str", "str"], return_type="Passenger")
+ def given_a_passenger(self, first_name, last_name):
+ passenger = self.persistence_context.create_passenger(first_name, last_name)
+ self.passengers.update({"{0} {1}".format(first_name, last_name): passenger})
+ return passenger
+
+ @TextSyntax("With age of #2 years", types=["Passenger", "int"])
+ def with_age_of_years(self, passenger, age):
+ passenger.age = age
+
+ @TextSyntax(["Given an Airplane #1"], types=["str"], return_type="AirplaneType")
+ def given_an_airplane(self, name):
+ airplane_type = self.persistence_context.create_airplane_type(name)
+ self.airplane_types.update({name: airplane_type})
+ return airplane_type
+
+ @TextSyntax(["Given a flight #1"], types=["str", "AirplaneType"], return_type="Flight")
+ def given_a_flight(self, name, airplane):
+ flight = self.persistence_context.create_flight(name)
+ flight.airplane = airplane
+ self.flights.update({name: flight})
+ return flight
+
+ @TextSyntax("that is executed using a #1", types=["str", "Flight"])
+ def that_is_executed_using_a(self, airplane_name, flight):
+ airplane = self.airplane_types.get(airplane_name)
+ flight.airplane = airplane
+
+ @TextSyntax("With #1 free seats", types=["int", "Flight"])
+ def with_free_seats(self, free_seats, flight):
+ flight.free_seats = free_seats
+
+ @TextSyntax("Book seat for #1 #2 at #3", types=["str", "str", "str"], return_type="OperationStatus")
+ def book_seat_for(self, first_name, last_name, flight_name):
+ passenger = self.passengers.get("{0} {1}".format(first_name, last_name))
+ flight = self.flights.get(flight_name)
+ return self.service.book_seat(passenger, flight)
+
+ @TextSyntax("Cancel seat for #1 #2 at #3", types=["str", "str", "str"], return_type="OperationStatus")
+ def cancel_seat_for(self, first_name, last_name, flight_name):
+ passenger = self.passengers.get("{0} {1}".format(first_name, last_name))
+ flight = self.flights.get("{0}".format(flight_name))
+ return self.service.cancel_seat(passenger, flight)
+
+ @TextSyntax(["Assume a valid ticket is issued", "Assume cancellation successful"], types=["OperationStatus"])
+ def assume_valid_ticket(self, status):
+ self.test_case.assertTrue(status.valid, msg=status.msg)
+
+
+ @TextSyntax("Assume no valid ticket is issued", types=["OperationStatus"])
+ def assume_no_valid_ticked_is_issued(self, status):
+ self.test_case.assertFalse(status.valid, msg=status.msg)
+
+
+ @TextSyntax("Assume #1 has passenger #2", types=["Flight", "Passenger"])
+ def assume_has_passenger(self, flight, passenger):
+ self.test_case.assertTrue(flight.has_passenger(passenger))
\ No newline at end of file
diff --git a/.svn/pristine/d8/d816e38e1691bd0ecddab1c9e062e51513934d76.svn-base b/.svn/pristine/d8/d816e38e1691bd0ecddab1c9e062e51513934d76.svn-base
new file mode 100644
index 0000000..5d63d3d
--- /dev/null
+++ b/.svn/pristine/d8/d816e38e1691bd0ecddab1c9e062e51513934d76.svn-base
@@ -0,0 +1,60 @@
+from natspec_utils.stringutils import stringToUnicode as u;
+
+import unittest
+from test.support import TestSupport
+from service.airline_service import AirlineService
+from persistence.in_memory_context import InMemoryPersistenceContext
+
+class BookSeatTwice(unittest.TestCase):
+ """This class serves as a template for all classes that are generated for
+ NatSpec scenarios (.natspec files). It is recognized by NatSpec based on its
+ special name and applies to all scenarios in the same package and all sub
+ packages (unless there is another template class in one of the sub packages).
+ This particular template is a unittest test case where the concrete steps of the
+ test are filled by the NatSpec code generator.
+ """
+
+ def setUp(self):
+ """Sets up the test environment (i.e., initialize the service class, the
+ entity manager and the test support class).
+ """
+ self.service = AirlineService()
+ self.persistence_context = InMemoryPersistenceContext()
+ self.test_support = TestSupport(self.service, self.persistence_context, self)
+
+ def test(self):
+ """
+ The code in this method is generated from: /de.devboost.natspec.example.python/test/scenarios/book_seat_twice.natspec
+ Never change this method or any contents of this file, all local changes will we overwritten.
+ """
+ # Given a Passenger John Doe
+ passenger_John_Doe = self.test_support.given_a_passenger(u("John"), u("Doe"))
+
+ # Given an Airplane Boeing-787
+ airplaneType_Boeing_787 = self.test_support.given_an_airplane(u("Boeing-787"))
+
+ # Given a flight LH-1234
+ flight_LH_1234 = self.test_support.given_a_flight(u("LH-1234"))
+
+ # that is executed using a Boeing-787
+ self.test_support.that_is_executed_using_a(u("Boeing-787"), flight_LH_1234)
+
+ # With 200 free seats
+ self.test_support.with_free_seats(200, flight_LH_1234)
+
+ # Book seat for John Doe at LH-1234
+ operationStatus_John_Doe_LH_1234 = self.test_support.book_seat_for(u("John"), u("Doe"), u("LH-1234"))
+
+ # Assume a valid ticket is issued
+ self.test_support.assume_valid_ticket(operationStatus_John_Doe_LH_1234)
+
+ # Book seat for John Doe at LH-1234
+ operationStatus_John_Doe_LH_12340 = self.test_support.book_seat_for(u("John"), u("Doe"), u("LH-1234"))
+
+ # Assume no valid ticket is issued
+ self.test_support.assume_no_valid_ticked_is_issued(operationStatus_John_Doe_LH_12340)
+
+
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
diff --git a/.svn/pristine/d9/d959df2075f8108ba5372980b6055561619bf9dd.svn-base b/.svn/pristine/d9/d959df2075f8108ba5372980b6055561619bf9dd.svn-base
new file mode 100644
index 0000000..cab196a
--- /dev/null
+++ b/.svn/pristine/d9/d959df2075f8108ba5372980b6055561619bf9dd.svn-base
@@ -0,0 +1,6 @@
+There needs to be a free seat for the passenger.
+There should be at least 0 free seats to handle overbooking.
+Each Passenger can only be booked once.
+
+// Optional rule:
+//The Passenger needs to be at least 18 years old.
diff --git a/.svn/pristine/da/da39a3ee5e6b4b0d3255bfef95601890afd80709.svn-base b/.svn/pristine/da/da39a3ee5e6b4b0d3255bfef95601890afd80709.svn-base
new file mode 100644
index 0000000..e69de29
diff --git a/.svn/pristine/e1/e13d580b976ccf399031d175149c378cb50f4164.svn-base b/.svn/pristine/e1/e13d580b976ccf399031d175149c378cb50f4164.svn-base
new file mode 100644
index 0000000..466919d
--- /dev/null
+++ b/.svn/pristine/e1/e13d580b976ccf399031d175149c378cb50f4164.svn-base
@@ -0,0 +1,51 @@
+from persistence import entities
+class InMemoryPersistenceContext(object):
+ __instance = None
+
+ class __impl(object):
+ def __init__(self):
+ self.flights = {}
+ self.airplanes = {}
+ self.passengers = {}
+
+ def update(self, entity):
+ update_dict = {entity.id: entity}
+ if isinstance(entity, entities.Flight):
+ self.flights.update(update_dict)
+ return
+ if isinstance(entity, entities.AirplaneType):
+ self.airplanes.update(update_dict)
+ return
+ if isinstance(entity, entities.Passenger):
+ self.passengers.update(update_dict)
+ return
+
+ def create_flight(self, name):
+ flight = entities.Flight(name)
+ self.update(flight)
+ return flight
+
+ def create_passenger(self, first_name, last_name):
+ passenger = entities.Passenger(first_name, last_name)
+ self.update(passenger)
+ return passenger
+
+ def create_airplane_type(self, name):
+ airplane_type = entities.AirplaneType(name)
+ self.update(airplane_type)
+ return airplane_type
+
+
+
+ def __init__(self):
+ if InMemoryPersistenceContext.__instance is None:
+ InMemoryPersistenceContext.__instance = InMemoryPersistenceContext.__impl()
+ self.__dict__['_InMemoryPersistenceContext__instance'] = InMemoryPersistenceContext.__instance
+
+ def __getattr__(self, attr):
+ """ Delegate access to implementation """
+ return getattr(self.__instance, attr)
+
+ def __setattr__(self, attr, value):
+ """ Delegate access to implementation """
+ return setattr(self.__instance, attr, value)
\ No newline at end of file
diff --git a/.svn/pristine/e4/e4a62745b544897db3e84e7732e9e371dc2fa230.svn-base b/.svn/pristine/e4/e4a62745b544897db3e84e7732e9e371dc2fa230.svn-base
new file mode 100644
index 0000000..cf507d2
--- /dev/null
+++ b/.svn/pristine/e4/e4a62745b544897db3e84e7732e9e371dc2fa230.svn-base
@@ -0,0 +1,48 @@
+from natspec_utils.stringutils import stringToUnicode as u;
+
+import unittest
+from test.support import TestSupport
+from service.airline_service import AirlineService
+from persistence.in_memory_context import InMemoryPersistenceContext
+
+class BookSeat(unittest.TestCase):
+ def __init__(self):
+ self.service = AirlineService()
+ self.test_support = TestSupport(self.service, self.persistence_context, self)
+ self.persistence_context = InMemoryPersistenceContext()
+
+ def setUp(self):
+ self.service = AirlineService()
+ self.persistence_context = InMemoryPersistenceContext()
+ self.test_support = TestSupport(self.service, self.persistence_context, self)
+
+ def test(self):
+ """
+ The code in this method is generated from: /de.devboost.natspec.example.python/test/scenarios/book_seat.natspec
+ Never change this method or any contents of this file, all local changes will we overwritten.
+ """
+ # Given a Passenger John Doe
+ passenger_John_Doe = self.test_support.given_a_passenger(u("John"), u("Doe"))
+
+ # Given an Airplane Boeing-787
+ airplaneType_Boeing_787 = self.test_support.given_an_airplane(u("Boeing-787"))
+
+ # Given a flight LH-1234
+ flight_LH_1234 = self.test_support.given_a_flight(u("LH-1234"), airplaneType_Boeing_787)
+
+ # that is executed using a Boeing-787
+ self.test_support.that_is_executed_using_a(u("Boeing-787"), flight_LH_1234)
+
+ # With 200 free seats
+ self.test_support.with_free_seats(200, flight_LH_1234)
+
+ # Book seat for John Doe at LH-1234
+ operationStatus_John_Doe_LH_1234 = self.test_support.book_seat_for(u("John"), u("Doe"), u("LH-1234"))
+
+ # Assume a valid ticket is issued
+ self.test_support.assume_valid_ticket(operationStatus_John_Doe_LH_1234)
+
+
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
diff --git a/.svn/pristine/e8/e86d9310f97e1b3fdd5b521ae7ad7abc3102456f.svn-base b/.svn/pristine/e8/e86d9310f97e1b3fdd5b521ae7ad7abc3102456f.svn-base
new file mode 100644
index 0000000..fe9255c
--- /dev/null
+++ b/.svn/pristine/e8/e86d9310f97e1b3fdd5b521ae7ad7abc3102456f.svn-base
@@ -0,0 +1,32 @@
+from service.validation.support import ValidationSupport
+
+class Rules(object):
+ """This class serves as a template for validation rule classes that are written
+ in plain natural language. The template is instantiated by NatSpec for all
+ the .natspec files in this package. The @MethodBody placeholder
+ in validate() is replaced with the code that performs the actual validation.
+ See class Rules for a concrete example validation class.
+ This class is an example of applying NatSpec for non-testing purposes.
+ """
+ def __init__(self, flight, passenger):
+ self.validation_support = ValidationSupport(flight, passenger)
+
+ def validate(self):
+ """Checks that all validation rules are met.
+ :returns: the status of the validation (i.e., success or failure).
+ """
+ """
+ The code in this method is generated from: /de.devboost.natspec.example.python/service/validation/rules.natspec
+ Never change this method or any contents of this file, all local changes will we overwritten.
+ """
+ # There needs to be a free seat for the passenger.
+ self.validation_support.check_free_seats()
+
+ # There should be at least 0 free seats to handle overbooking.
+ self.validation_support.check_free_seats_with_buffer(0)
+
+ # Each Passenger can only be booked once.
+ self.validation_support.check_unique_passenger()
+
+
+ return self.validation_support.status
\ No newline at end of file
diff --git a/.svn/pristine/ef/ef1bedbc0450b71269db733433eccc98d58ba917.svn-base b/.svn/pristine/ef/ef1bedbc0450b71269db733433eccc98d58ba917.svn-base
new file mode 100644
index 0000000..9bc04bc
--- /dev/null
+++ b/.svn/pristine/ef/ef1bedbc0450b71269db733433eccc98d58ba917.svn-base
@@ -0,0 +1,75 @@
+from persistence import entities
+class InMemoryPersistenceContext(object):
+ """The InMemoryPersistenceContext is a very basic store for entity
+ objects. It basically holds all objects in memory. In a real application,
+ this will probably be replaced by a Data Access Object (DAO) that retrieves
+ object from and stores objects to a database."""
+
+ # This fields holds the single instance of this class.
+ __instance = None
+
+ class __impl(object):
+ def __init__(self):
+ self.flights = {}
+ self.airplanes = {}
+ self.passengers = {}
+
+ def update(self, entity):
+ """Stores the given entity.
+ :param entity: the entity to store
+ """
+ update_dict = {entity.id: entity}
+ if isinstance(entity, entities.Flight):
+ self.flights.update(update_dict)
+ return
+ if isinstance(entity, entities.AirplaneType):
+ self.airplanes.update(update_dict)
+ return
+ if isinstance(entity, entities.Passenger):
+ self.passengers.update(update_dict)
+ return
+
+ def create_flight(self, name):
+ """Creates a new flight with the given name.
+ :param name: the name of the flight.
+ :returns: the created object
+ """
+ flight = entities.Flight(name)
+ self.update(flight)
+ return flight
+
+ def create_passenger(self, first_name, last_name):
+ """Creates a new passenger with the given first and last name.
+ :param first_name: the first name of the passenger.
+ :param last_name: the name of the passenger.
+ :returns: the created object
+ """
+ passenger = entities.Passenger(first_name, last_name)
+ self.update(passenger)
+ return passenger
+
+
+ def create_airplane_type(self, name):
+ """Creates a new type of airplane with the given name.
+ :param name: the name of the airplane type.
+ :returns: the created object.
+ """
+ airplane_type = entities.AirplaneType(name)
+ self.update(airplane_type)
+ return airplane_type
+
+
+ def __init__(self):
+ """Creates the one and only instance of this class."""
+
+ if InMemoryPersistenceContext.__instance is None:
+ InMemoryPersistenceContext.__instance = InMemoryPersistenceContext.__impl()
+ self.__dict__['_InMemoryPersistenceContext__instance'] = InMemoryPersistenceContext.__instance
+
+ def __getattr__(self, attr):
+ """Delegate access to implementation"""
+ return getattr(self.__instance, attr)
+
+ def __setattr__(self, attr, value):
+ """Delegate access to implementation"""
+ return setattr(self.__instance, attr, value)
diff --git a/.svn/pristine/f6/f6273168fee1f361737a1e0ab4ba8f6c73eae2ee.svn-base b/.svn/pristine/f6/f6273168fee1f361737a1e0ab4ba8f6c73eae2ee.svn-base
new file mode 100644
index 0000000..2cc5335
--- /dev/null
+++ b/.svn/pristine/f6/f6273168fee1f361737a1e0ab4ba8f6c73eae2ee.svn-base
@@ -0,0 +1,43 @@
+from natspec_utils.stringutils import stringToUnicode as u;
+
+import unittest
+from test.support import TestSupport
+from service.airline_service import AirlineService
+from persistence.in_memory_context import InMemoryPersistenceContext
+
+class BookSeat(unittest.TestCase):
+ def setUp(self):
+ self.service = AirlineService()
+ self.persistence_context = InMemoryPersistenceContext()
+ self.test_support = TestSupport(self.service, self.persistence_context, self)
+
+ def test(self):
+ """
+ The code in this method is generated from: /de.devboost.natspec.example.python/test/scenarios/book_seat.natspec
+ Never change this method or any contents of this file, all local changes will we overwritten.
+ """
+ # Given a Passenger John Doe
+ passenger_John_Doe = self.test_support.given_a_passenger(u("John"), u("Doe"))
+
+ # Given an Airplane Boeing-787
+ airplaneType_Boeing_787 = self.test_support.given_an_airplane(u("Boeing-787"))
+
+ # Given a flight LH-1234
+ flight_LH_1234 = self.test_support.given_a_flight(u("LH-1234"), airplaneType_Boeing_787)
+
+ # that is executed using a Boeing-787
+ self.test_support.that_is_executed_using_a(u("Boeing-787"), flight_LH_1234)
+
+ # With 200 free seats
+ self.test_support.with_free_seats(200, flight_LH_1234)
+
+ # Book seat for John Doe at LH-1234
+ operationStatus_John_Doe_LH_1234 = self.test_support.book_seat_for(u("John"), u("Doe"), u("LH-1234"))
+
+ # Assume a valid ticket is issued
+ self.test_support.assume_valid_ticket(operationStatus_John_Doe_LH_1234)
+
+
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
diff --git a/.svn/pristine/f8/f875d0cbf0db56b5878ce800672c9b8efb6e7f90.svn-base b/.svn/pristine/f8/f875d0cbf0db56b5878ce800672c9b8efb6e7f90.svn-base
new file mode 100644
index 0000000..296dc38
--- /dev/null
+++ b/.svn/pristine/f8/f875d0cbf0db56b5878ce800672c9b8efb6e7f90.svn-base
@@ -0,0 +1,66 @@
+from natspec_utils.stringutils import stringToUnicode as u;
+
+import unittest
+from test.support import TestSupport
+from service.airline_service import AirlineService
+from persistence.in_memory_context import InMemoryPersistenceContext
+
+class CancelSeatTwice(unittest.TestCase):
+ """This class serves as a template for all classes that are generated for
+ NatSpec scenarios (.natspec files). It is recognized by NatSpec based on its
+ special name and applies to all scenarios in the same package and all sub
+ packages (unless there is another template class in one of the sub packages).
+ This particular template is a unittest test case where the concrete steps of the
+ test are filled by the NatSpec code generator.
+ """
+
+ def setUp(self):
+ """Sets up the test environment (i.e., initialize the service class, the
+ entity manager and the test support class).
+ """
+ self.service = AirlineService()
+ self.persistence_context = InMemoryPersistenceContext()
+ self.test_support = TestSupport(self.service, self.persistence_context, self)
+
+ def test(self):
+ """
+ The code in this method is generated from: /de.devboost.natspec.example.python/test/scenarios/cancel_seat_twice.natspec
+ Never change this method or any contents of this file, all local changes will we overwritten.
+ """
+ # Given an airplane Boeing-737-600
+ airplaneType_Boeing_737_600 = self.test_support.given_an_airplane(u("Boeing-737-600"))
+
+ # Given a flight LH-1234
+ flight_LH_1234 = self.test_support.given_a_flight(u("LH-1234"))
+
+ # that is executed using a Boeing-737-600
+ self.test_support.that_is_executed_using_a(u("Boeing-737-600"), flight_LH_1234)
+
+ # With 2 free seats
+ self.test_support.with_free_seats(2, flight_LH_1234)
+
+ # Given a passenger John Doe
+ passenger_John_Doe = self.test_support.given_a_passenger(u("John"), u("Doe"))
+
+ # Book seat for John Doe at LH-1234
+ operationStatus_John_Doe_LH_1234 = self.test_support.book_seat_for(u("John"), u("Doe"), u("LH-1234"))
+
+ # Assume a valid ticket is issued
+ self.test_support.assume_valid_ticket(operationStatus_John_Doe_LH_1234)
+
+ # Cancel seat for John Doe at LH-1234
+ operationStatus_John_Doe_LH_12340 = self.test_support.cancel_seat_for(u("John"), u("Doe"), u("LH-1234"))
+
+ # Assume a valid ticket is issued
+ self.test_support.assume_valid_ticket(operationStatus_John_Doe_LH_12340)
+
+ # Cancel seat for John Doe at LH-1234
+ operationStatus_John_Doe_LH_12341 = self.test_support.cancel_seat_for(u("John"), u("Doe"), u("LH-1234"))
+
+ # Assume no valid ticket is issued
+ self.test_support.assume_no_valid_ticked_is_issued(operationStatus_John_Doe_LH_12341)
+
+
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
diff --git a/.svn/pristine/ff/ff899aefbb51e54d5916877a0b5f3bd22470825e.svn-base b/.svn/pristine/ff/ff899aefbb51e54d5916877a0b5f3bd22470825e.svn-base
new file mode 100644
index 0000000..bf66e34
--- /dev/null
+++ b/.svn/pristine/ff/ff899aefbb51e54d5916877a0b5f3bd22470825e.svn-base
@@ -0,0 +1,20 @@
+import unittest
+from test.support import TestSupport
+from service.airline_service import AirlineService
+from persistence.in_memory_context import InMemoryPersistenceContext
+
+class CancelSeatTwice(unittest.TestCase):
+ def setUp(self):
+ self.service = AirlineService()
+ self.persistence_context = InMemoryPersistenceContext()
+ self.test_support = TestSupport(self.service, self.persistence_context, self)
+
+ def test(self):
+ """
+ The code in this method is generated from: /de.devboost.natspec.example.python/test/scenarios/cancel_seat_twice.natspec
+ Never change this method or any contents of this file, all local changes will we overwritten.
+ """
+
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
diff --git a/.svn/wc.db b/.svn/wc.db
new file mode 100644
index 0000000..fbcf3bb
Binary files /dev/null and b/.svn/wc.db differ
diff --git a/persistence/__init__.py b/persistence/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/persistence/entities.py b/persistence/entities.py
new file mode 100644
index 0000000..e2e2116
--- /dev/null
+++ b/persistence/entities.py
@@ -0,0 +1,90 @@
+class Entity(object):
+ # A global counter that holds the next available entity ID.
+ _counter = 0
+
+ def __init__(self):
+ """Creates a new entity and initialized its ID."""
+ Entity._counter += 1
+ self.id = Entity._counter
+
+
+class NamedEntity(Entity):
+ """This is a super class for all entities that carry a name."""
+ def __init__(self, name):
+ super(NamedEntity, self).__init__()
+ self.name = name
+
+
+class Passenger(Entity):
+ """A Passenger object represents a person who can be booked on flights."""
+
+ def __init__(self, first_name, last_name):
+ """Creates a new passenger with the given first and last name, having an initial ago of zero.
+ :param firstname: the first name of the passenger.
+ :param lastname: the last name of the passenger.
+ """
+ super(Passenger, self).__init__()
+ self.first_name = first_name
+ self.last_name = last_name
+ self.age = 0
+
+class Flight(NamedEntity):
+ """A Flight represents the opportunity to travel from one airport to another.
+ Each Flight is executed using a particular type of airplane and holds a limited amount of passengers.
+ """
+
+ def __init__(self, name):
+ """Creates a new flight with the given name.
+ :param name: the new name for the flight.
+ """
+ super(Flight, self).__init__(name)
+ self.__airplane = None
+ self.passenger_ids = []
+ self.__free_seats = 0
+
+ @property
+ def airplane(self):
+ return self._airplane
+
+ @airplane.setter
+ def airplane(self, value):
+ self.__airplane = value
+ self.__free_seats = value.total_seats
+
+ @property
+ def free_seats(self):
+ return self.__free_seats - len(self.passenger_ids)
+
+ @free_seats.setter
+ def free_seats(self, value):
+ self.__free_seats = value
+
+ def has_passenger(self, passenger):
+ return passenger.id in self.passenger_ids
+
+ def add_passenger(self, passenger):
+ self.passenger_ids.append(passenger.id)
+
+ def remove_passenger(self, passenger):
+ if passenger.id in self.passenger_ids:
+ self.passenger_ids.remove(passenger.id)
+ return True
+ return False
+
+
+class AirplaneType(NamedEntity):
+ """An AirplaneType represents a specific typo of airplane which is
+ characterized by its name and a number of total seats.
+ """
+
+ def __init__(self, name):
+ """Creates a new AirplaneType entity with the given name.
+ :param name: the name of the type of airplane.
+ """
+ super(AirplaneType, self).__init__(name)
+ self.total_seats = 0
+
+
+
+
+
diff --git a/persistence/in_memory_context.py b/persistence/in_memory_context.py
new file mode 100644
index 0000000..9bc04bc
--- /dev/null
+++ b/persistence/in_memory_context.py
@@ -0,0 +1,75 @@
+from persistence import entities
+class InMemoryPersistenceContext(object):
+ """The InMemoryPersistenceContext is a very basic store for entity
+ objects. It basically holds all objects in memory. In a real application,
+ this will probably be replaced by a Data Access Object (DAO) that retrieves
+ object from and stores objects to a database."""
+
+ # This fields holds the single instance of this class.
+ __instance = None
+
+ class __impl(object):
+ def __init__(self):
+ self.flights = {}
+ self.airplanes = {}
+ self.passengers = {}
+
+ def update(self, entity):
+ """Stores the given entity.
+ :param entity: the entity to store
+ """
+ update_dict = {entity.id: entity}
+ if isinstance(entity, entities.Flight):
+ self.flights.update(update_dict)
+ return
+ if isinstance(entity, entities.AirplaneType):
+ self.airplanes.update(update_dict)
+ return
+ if isinstance(entity, entities.Passenger):
+ self.passengers.update(update_dict)
+ return
+
+ def create_flight(self, name):
+ """Creates a new flight with the given name.
+ :param name: the name of the flight.
+ :returns: the created object
+ """
+ flight = entities.Flight(name)
+ self.update(flight)
+ return flight
+
+ def create_passenger(self, first_name, last_name):
+ """Creates a new passenger with the given first and last name.
+ :param first_name: the first name of the passenger.
+ :param last_name: the name of the passenger.
+ :returns: the created object
+ """
+ passenger = entities.Passenger(first_name, last_name)
+ self.update(passenger)
+ return passenger
+
+
+ def create_airplane_type(self, name):
+ """Creates a new type of airplane with the given name.
+ :param name: the name of the airplane type.
+ :returns: the created object.
+ """
+ airplane_type = entities.AirplaneType(name)
+ self.update(airplane_type)
+ return airplane_type
+
+
+ def __init__(self):
+ """Creates the one and only instance of this class."""
+
+ if InMemoryPersistenceContext.__instance is None:
+ InMemoryPersistenceContext.__instance = InMemoryPersistenceContext.__impl()
+ self.__dict__['_InMemoryPersistenceContext__instance'] = InMemoryPersistenceContext.__instance
+
+ def __getattr__(self, attr):
+ """Delegate access to implementation"""
+ return getattr(self.__instance, attr)
+
+ def __setattr__(self, attr, value):
+ """Delegate access to implementation"""
+ return setattr(self.__instance, attr, value)
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..b561c84
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1 @@
+natspec_utils
diff --git a/service/__init__.py b/service/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/service/airline_service.py b/service/airline_service.py
new file mode 100644
index 0000000..578cbcd
--- /dev/null
+++ b/service/airline_service.py
@@ -0,0 +1,36 @@
+from service.validation.rules import Rules
+from service.status import OperationStatus
+
+class AirlineService(object):
+ """The AirlineService provides very basic business functionality for the
+ airline domain. It allows to book seats for passengers on flights
+ and to cancel these seats.
+ """
+
+ def book_seat(self, passenger, flight):
+ """Tries to book a seat for the given passenger on the given flight. Before
+ the seat is actually booked some validation rules are checked to make
+ sure the constraints of the domain (e.g., that a passenger can book at
+ most one seat for a flight) are met. If one of the validation rules is
+ violated, this operation fails.
+ :param flight: the flight to book the seat on.
+ :param passenger: the passenger to book the seat for.
+ :returns: a status object representing the operations success (or failure).
+ """
+ rules = Rules(flight, passenger)
+ status = rules.validate()
+ if status.valid:
+ flight.add_passenger(passenger)
+ return status
+
+ def cancel_seat(self, passenger, flight):
+ """Cancels the seat booked by the given passenger on the given flight. This
+ operation can fail if the passenger has not booked a seat on the given
+ flight.
+ :param passenger: the passenger to cancel the seat for.
+ :param flight: the flight to cancel the seat on.
+ :returns: a status object representing the operations success (or failure).
+ """
+ if flight.remove_passenger(passenger):
+ return OperationStatus("Passenger was removed", True)
+ return OperationStatus("Passenger was not booked on flight", False)
\ No newline at end of file
diff --git a/service/status.py b/service/status.py
new file mode 100644
index 0000000..94a56ba
--- /dev/null
+++ b/service/status.py
@@ -0,0 +1,9 @@
+class OperationStatus(object):
+ """Objects of type OperationStatus are used to capture the result of
+ business operations. Each result comprises of a message and a validity flag
+ which indicates success or failure of the operation.
+ """
+
+ def __init__(self, msg="", status=True):
+ self.msg = msg
+ self.valid = status
\ No newline at end of file
diff --git a/service/validation/_NatSpecTemplate.py b/service/validation/_NatSpecTemplate.py
new file mode 100644
index 0000000..3b42876
--- /dev/null
+++ b/service/validation/_NatSpecTemplate.py
@@ -0,0 +1,19 @@
+from service.validation.support import ValidationSupport
+
+class _NatSpecTemplate(object):
+ """This class serves as a template for validation rule classes that are written
+ in plain natural language. The template is instantiated by NatSpec for all
+ the .natspec files in this package. The @MethodBody placeholder
+ in validate() is replaced with the code that performs the actual validation.
+ See class Rules for a concrete example validation class.
+ This class is an example of applying NatSpec for non-testing purposes.
+ """
+ def __init__(self, flight, passenger):
+ self.validation_support = ValidationSupport(flight, passenger)
+
+ def validate(self):
+ """Checks that all validation rules are met.
+ :returns: the status of the validation (i.e., success or failure).
+ """
+ """ @MethodBody """
+ return self.validation_support.status
\ No newline at end of file
diff --git a/service/validation/__init__.py b/service/validation/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/service/validation/rules.natspec b/service/validation/rules.natspec
new file mode 100644
index 0000000..cab196a
--- /dev/null
+++ b/service/validation/rules.natspec
@@ -0,0 +1,6 @@
+There needs to be a free seat for the passenger.
+There should be at least 0 free seats to handle overbooking.
+Each Passenger can only be booked once.
+
+// Optional rule:
+//The Passenger needs to be at least 18 years old.
diff --git a/service/validation/rules.py b/service/validation/rules.py
new file mode 100644
index 0000000..fe9255c
--- /dev/null
+++ b/service/validation/rules.py
@@ -0,0 +1,32 @@
+from service.validation.support import ValidationSupport
+
+class Rules(object):
+ """This class serves as a template for validation rule classes that are written
+ in plain natural language. The template is instantiated by NatSpec for all
+ the .natspec files in this package. The @MethodBody placeholder
+ in validate() is replaced with the code that performs the actual validation.
+ See class Rules for a concrete example validation class.
+ This class is an example of applying NatSpec for non-testing purposes.
+ """
+ def __init__(self, flight, passenger):
+ self.validation_support = ValidationSupport(flight, passenger)
+
+ def validate(self):
+ """Checks that all validation rules are met.
+ :returns: the status of the validation (i.e., success or failure).
+ """
+ """
+ The code in this method is generated from: /de.devboost.natspec.example.python/service/validation/rules.natspec
+ Never change this method or any contents of this file, all local changes will we overwritten.
+ """
+ # There needs to be a free seat for the passenger.
+ self.validation_support.check_free_seats()
+
+ # There should be at least 0 free seats to handle overbooking.
+ self.validation_support.check_free_seats_with_buffer(0)
+
+ # Each Passenger can only be booked once.
+ self.validation_support.check_unique_passenger()
+
+
+ return self.validation_support.status
\ No newline at end of file
diff --git a/service/validation/support.py b/service/validation/support.py
new file mode 100644
index 0000000..4f359fd
--- /dev/null
+++ b/service/validation/support.py
@@ -0,0 +1,50 @@
+from service.status import OperationStatus
+from natspec_utils.decorators import TextSyntax
+class ValidationSupport():
+ """The ValidationSupport call defined all methods that are required to
+ execute the textual validation rules present in this example.
+ """
+
+ def __init__(self, flight, passenger):
+ """Creates a new instance of this class that can be used to validate the
+ given flight and passenger.
+
+ :param flight: the flight to validate.
+ :param passenger: the passenger to validate.
+ """
+ self.flight = flight
+ self.passenger = passenger
+ self.status = OperationStatus()
+
+ def set_invalid(self, msg):
+ """Sets the status of this validation to invalid (failure) and adds the given message.
+ :param msg: the message to add.
+ """
+ self.status.valid = False
+ self.status.msg = msg
+
+ @TextSyntax("Each Passenger can only be booked once.")
+ def check_unique_passenger(self):
+ """Checks that the passenger has not already booked a seat on this flight."""
+ if self.passenger.id in self.flight.passenger_ids:
+ self.set_invalid("A passenger can only be booked once for each flight.")
+
+ @TextSyntax("There should be at least #1 free seats to handle overbooking.", types=["int"])
+ def check_free_seats_with_buffer(self, overbooking_buffer):
+ """Checks that the given number of seats is held free."""
+ if self.flight.free_seats < overbooking_buffer:
+ self.set_invalid("There are no free seats for the flight.")
+
+ @TextSyntax("There needs to be a free seat for the passenger.")
+ def check_free_seats(self):
+ """Checks that there is at least one seat available."""
+ if self.flight.free_seats < 1:
+ self.set_invalid("There are no free seats for the flight.")
+
+ @TextSyntax("The Passenger needs to be at least #1 years old.", types=["int"])
+ def passenger_needs_to_be_at_least_years_old(self, minimal_age):
+ """Checks that the passenger has at least the given age (in years)."""
+ if self.passenger.age < minimal_age:
+ self.set_invalid("The passenger needs to be at least {0} years.".format(minimal_age))
+
+
diff --git a/test/__init__.py b/test/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/test/scenarios/_NatSpecTemplate.py b/test/scenarios/_NatSpecTemplate.py
new file mode 100644
index 0000000..06940f6
--- /dev/null
+++ b/test/scenarios/_NatSpecTemplate.py
@@ -0,0 +1,27 @@
+import unittest
+from test.support import TestSupport
+from service.airline_service import AirlineService
+from persistence.in_memory_context import InMemoryPersistenceContext
+
+class _NatSpecTemplate(unittest.TestCase):
+ """This class serves as a template for all classes that are generated for
+ NatSpec scenarios (.natspec files). It is recognized by NatSpec based on its
+ special name and applies to all scenarios in the same package and all sub
+ packages (unless there is another template class in one of the sub packages).
+ This particular template is a unittest test case where the concrete steps of the
+ test are filled by the NatSpec code generator.
+ """
+
+ def setUp(self):
+ """Sets up the test environment (i.e., initialize the service class, the
+ entity manager and the test support class).
+ """
+ self.service = AirlineService()
+ self.persistence_context = InMemoryPersistenceContext()
+ self.test_support = TestSupport(self.service, self.persistence_context, self)
+
+ def test(self):
+ """ @MethodBody """
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
diff --git a/test/scenarios/__init__.py b/test/scenarios/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/test/scenarios/book_seat.natspec b/test/scenarios/book_seat.natspec
new file mode 100644
index 0000000..ba848a1
--- /dev/null
+++ b/test/scenarios/book_seat.natspec
@@ -0,0 +1,13 @@
+// This scenario describes a simple booking process
+// for an exemplary passenger
+
+Given a Passenger John Doe
+Given an Airplane Boeing-787
+
+Given a flight LH-1234
+ that is executed using a Boeing-787
+ With 200 free seats
+
+Book seat for John Doe at LH-1234
+
+Assume a valid ticket is issued
\ No newline at end of file
diff --git a/test/scenarios/book_seat.py b/test/scenarios/book_seat.py
new file mode 100644
index 0000000..60010c6
--- /dev/null
+++ b/test/scenarios/book_seat.py
@@ -0,0 +1,54 @@
+from natspec_utils.stringutils import stringToUnicode as u;
+
+import unittest
+from test.support import TestSupport
+from service.airline_service import AirlineService
+from persistence.in_memory_context import InMemoryPersistenceContext
+
+class BookSeat(unittest.TestCase):
+ """This class serves as a template for all classes that are generated for
+ NatSpec scenarios (.natspec files). It is recognized by NatSpec based on its
+ special name and applies to all scenarios in the same package and all sub
+ packages (unless there is another template class in one of the sub packages).
+ This particular template is a unittest test case where the concrete steps of the
+ test are filled by the NatSpec code generator.
+ """
+
+ def setUp(self):
+ """Sets up the test environment (i.e., initialize the service class, the
+ entity manager and the test support class).
+ """
+ self.service = AirlineService()
+ self.persistence_context = InMemoryPersistenceContext()
+ self.test_support = TestSupport(self.service, self.persistence_context, self)
+
+ def test(self):
+ """
+ The code in this method is generated from: /de.devboost.natspec.example.python/test/scenarios/book_seat.natspec
+ Never change this method or any contents of this file, all local changes will we overwritten.
+ """
+ # Given a Passenger John Doe
+ passenger_John_Doe = self.test_support.given_a_passenger(u("John"), u("Doe"))
+
+ # Given an Airplane Boeing-787
+ airplaneType_Boeing_787 = self.test_support.given_an_airplane(u("Boeing-787"))
+
+ # Given a flight LH-1234
+ flight_LH_1234 = self.test_support.given_a_flight(u("LH-1234"))
+
+ # that is executed using a Boeing-787
+ self.test_support.that_is_executed_using_a(u("Boeing-787"), flight_LH_1234)
+
+ # With 200 free seats
+ self.test_support.with_free_seats(200, flight_LH_1234)
+
+ # Book seat for John Doe at LH-1234
+ operationStatus_John_Doe_LH_1234 = self.test_support.book_seat_for(u("John"), u("Doe"), u("LH-1234"))
+
+ # Assume a valid ticket is issued
+ self.test_support.assume_valid_ticket(operationStatus_John_Doe_LH_1234)
+
+
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
diff --git a/test/scenarios/book_seat_twice.natspec b/test/scenarios/book_seat_twice.natspec
new file mode 100644
index 0000000..2478004
--- /dev/null
+++ b/test/scenarios/book_seat_twice.natspec
@@ -0,0 +1,15 @@
+// This scenario describes an erroneous booking example
+// where the same passenger is booked twice for one flight
+
+Given a Passenger John Doe
+Given an Airplane Boeing-787
+Given a flight LH-1234
+ that is executed using a Boeing-787
+ With 200 free seats
+
+Book seat for John Doe at LH-1234
+ Assume a valid ticket is issued
+
+// Second booking for the same passenger should fail
+Book seat for John Doe at LH-1234
+ Assume no valid ticket is issued
\ No newline at end of file
diff --git a/test/scenarios/book_seat_twice.py b/test/scenarios/book_seat_twice.py
new file mode 100644
index 0000000..5d63d3d
--- /dev/null
+++ b/test/scenarios/book_seat_twice.py
@@ -0,0 +1,60 @@
+from natspec_utils.stringutils import stringToUnicode as u;
+
+import unittest
+from test.support import TestSupport
+from service.airline_service import AirlineService
+from persistence.in_memory_context import InMemoryPersistenceContext
+
+class BookSeatTwice(unittest.TestCase):
+ """This class serves as a template for all classes that are generated for
+ NatSpec scenarios (.natspec files). It is recognized by NatSpec based on its
+ special name and applies to all scenarios in the same package and all sub
+ packages (unless there is another template class in one of the sub packages).
+ This particular template is a unittest test case where the concrete steps of the
+ test are filled by the NatSpec code generator.
+ """
+
+ def setUp(self):
+ """Sets up the test environment (i.e., initialize the service class, the
+ entity manager and the test support class).
+ """
+ self.service = AirlineService()
+ self.persistence_context = InMemoryPersistenceContext()
+ self.test_support = TestSupport(self.service, self.persistence_context, self)
+
+ def test(self):
+ """
+ The code in this method is generated from: /de.devboost.natspec.example.python/test/scenarios/book_seat_twice.natspec
+ Never change this method or any contents of this file, all local changes will we overwritten.
+ """
+ # Given a Passenger John Doe
+ passenger_John_Doe = self.test_support.given_a_passenger(u("John"), u("Doe"))
+
+ # Given an Airplane Boeing-787
+ airplaneType_Boeing_787 = self.test_support.given_an_airplane(u("Boeing-787"))
+
+ # Given a flight LH-1234
+ flight_LH_1234 = self.test_support.given_a_flight(u("LH-1234"))
+
+ # that is executed using a Boeing-787
+ self.test_support.that_is_executed_using_a(u("Boeing-787"), flight_LH_1234)
+
+ # With 200 free seats
+ self.test_support.with_free_seats(200, flight_LH_1234)
+
+ # Book seat for John Doe at LH-1234
+ operationStatus_John_Doe_LH_1234 = self.test_support.book_seat_for(u("John"), u("Doe"), u("LH-1234"))
+
+ # Assume a valid ticket is issued
+ self.test_support.assume_valid_ticket(operationStatus_John_Doe_LH_1234)
+
+ # Book seat for John Doe at LH-1234
+ operationStatus_John_Doe_LH_12340 = self.test_support.book_seat_for(u("John"), u("Doe"), u("LH-1234"))
+
+ # Assume no valid ticket is issued
+ self.test_support.assume_no_valid_ticked_is_issued(operationStatus_John_Doe_LH_12340)
+
+
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
diff --git a/test/scenarios/cancel_and_rebook_seat.natspec b/test/scenarios/cancel_and_rebook_seat.natspec
new file mode 100644
index 0000000..281acfc
--- /dev/null
+++ b/test/scenarios/cancel_and_rebook_seat.natspec
@@ -0,0 +1,24 @@
+Given an airplane Boeing-737-600
+
+Given a flight LH-1234
+ that is executed using a Boeing-737-600
+ With 1 free seats
+
+Given a passenger John Doe
+Given a passenger Jane Mejer
+
+// first passenger
+Book seat for John Doe at LH-1234
+ Assume a valid ticket is issued
+
+// second passenger
+Book seat for Jane Mejer at LH-1234
+ Assume no valid ticket is issued
+
+// cancel first passenger
+Cancel seat for John Doe at LH-1234
+ Assume cancellation successful
+
+// rebook second passenger on now free set
+Book seat for Jane Mejer at LH-1234
+ Assume a valid ticket is issued
diff --git a/test/scenarios/cancel_and_rebook_seat.py b/test/scenarios/cancel_and_rebook_seat.py
new file mode 100644
index 0000000..df16336
--- /dev/null
+++ b/test/scenarios/cancel_and_rebook_seat.py
@@ -0,0 +1,75 @@
+from natspec_utils.stringutils import stringToUnicode as u;
+
+import unittest
+from test.support import TestSupport
+from service.airline_service import AirlineService
+from persistence.in_memory_context import InMemoryPersistenceContext
+
+class CancelAndRebookSeat(unittest.TestCase):
+ """This class serves as a template for all classes that are generated for
+ NatSpec scenarios (.natspec files). It is recognized by NatSpec based on its
+ special name and applies to all scenarios in the same package and all sub
+ packages (unless there is another template class in one of the sub packages).
+ This particular template is a unittest test case where the concrete steps of the
+ test are filled by the NatSpec code generator.
+ """
+
+ def setUp(self):
+ """Sets up the test environment (i.e., initialize the service class, the
+ entity manager and the test support class).
+ """
+ self.service = AirlineService()
+ self.persistence_context = InMemoryPersistenceContext()
+ self.test_support = TestSupport(self.service, self.persistence_context, self)
+
+ def test(self):
+ """
+ The code in this method is generated from: /de.devboost.natspec.example.python/test/scenarios/cancel_and_rebook_seat.natspec
+ Never change this method or any contents of this file, all local changes will we overwritten.
+ """
+ # Given an airplane Boeing-737-600
+ airplaneType_Boeing_737_600 = self.test_support.given_an_airplane(u("Boeing-737-600"))
+
+ # Given a flight LH-1234
+ flight_LH_1234 = self.test_support.given_a_flight(u("LH-1234"))
+
+ # that is executed using a Boeing-737-600
+ self.test_support.that_is_executed_using_a(u("Boeing-737-600"), flight_LH_1234)
+
+ # With 1 free seats
+ self.test_support.with_free_seats(1, flight_LH_1234)
+
+ # Given a passenger John Doe
+ passenger_John_Doe = self.test_support.given_a_passenger(u("John"), u("Doe"))
+
+ # Given a passenger Jane Mejer
+ passenger_Jane_Mejer = self.test_support.given_a_passenger(u("Jane"), u("Mejer"))
+
+ # Book seat for John Doe at LH-1234
+ operationStatus_John_Doe_LH_1234 = self.test_support.book_seat_for(u("John"), u("Doe"), u("LH-1234"))
+
+ # Assume a valid ticket is issued
+ self.test_support.assume_valid_ticket(operationStatus_John_Doe_LH_1234)
+
+ # Book seat for Jane Mejer at LH-1234
+ operationStatus_Jane_Mejer_LH_1234 = self.test_support.book_seat_for(u("Jane"), u("Mejer"), u("LH-1234"))
+
+ # Assume no valid ticket is issued
+ self.test_support.assume_no_valid_ticked_is_issued(operationStatus_Jane_Mejer_LH_1234)
+
+ # Cancel seat for John Doe at LH-1234
+ operationStatus_John_Doe_LH_12340 = self.test_support.cancel_seat_for(u("John"), u("Doe"), u("LH-1234"))
+
+ # Assume cancellation successful
+ self.test_support.assume_valid_ticket(operationStatus_John_Doe_LH_12340)
+
+ # Book seat for Jane Mejer at LH-1234
+ operationStatus_Jane_Mejer_LH_12340 = self.test_support.book_seat_for(u("Jane"), u("Mejer"), u("LH-1234"))
+
+ # Assume a valid ticket is issued
+ self.test_support.assume_valid_ticket(operationStatus_Jane_Mejer_LH_12340)
+
+
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
diff --git a/test/scenarios/cancel_seat_twice.natspec b/test/scenarios/cancel_seat_twice.natspec
new file mode 100644
index 0000000..10705ba
--- /dev/null
+++ b/test/scenarios/cancel_seat_twice.natspec
@@ -0,0 +1,18 @@
+Given an airplane Boeing-737-600
+
+Given a flight LH-1234
+ that is executed using a Boeing-737-600
+ With 2 free seats
+
+Given a passenger John Doe
+
+// first passenger
+Book seat for John Doe at LH-1234
+ Assume a valid ticket is issued
+
+// cancel first passenger
+Cancel seat for John Doe at LH-1234
+ Assume a valid ticket is issued
+
+Cancel seat for John Doe at LH-1234
+ Assume no valid ticket is issued
diff --git a/test/scenarios/cancel_seat_twice.py b/test/scenarios/cancel_seat_twice.py
new file mode 100644
index 0000000..296dc38
--- /dev/null
+++ b/test/scenarios/cancel_seat_twice.py
@@ -0,0 +1,66 @@
+from natspec_utils.stringutils import stringToUnicode as u;
+
+import unittest
+from test.support import TestSupport
+from service.airline_service import AirlineService
+from persistence.in_memory_context import InMemoryPersistenceContext
+
+class CancelSeatTwice(unittest.TestCase):
+ """This class serves as a template for all classes that are generated for
+ NatSpec scenarios (.natspec files). It is recognized by NatSpec based on its
+ special name and applies to all scenarios in the same package and all sub
+ packages (unless there is another template class in one of the sub packages).
+ This particular template is a unittest test case where the concrete steps of the
+ test are filled by the NatSpec code generator.
+ """
+
+ def setUp(self):
+ """Sets up the test environment (i.e., initialize the service class, the
+ entity manager and the test support class).
+ """
+ self.service = AirlineService()
+ self.persistence_context = InMemoryPersistenceContext()
+ self.test_support = TestSupport(self.service, self.persistence_context, self)
+
+ def test(self):
+ """
+ The code in this method is generated from: /de.devboost.natspec.example.python/test/scenarios/cancel_seat_twice.natspec
+ Never change this method or any contents of this file, all local changes will we overwritten.
+ """
+ # Given an airplane Boeing-737-600
+ airplaneType_Boeing_737_600 = self.test_support.given_an_airplane(u("Boeing-737-600"))
+
+ # Given a flight LH-1234
+ flight_LH_1234 = self.test_support.given_a_flight(u("LH-1234"))
+
+ # that is executed using a Boeing-737-600
+ self.test_support.that_is_executed_using_a(u("Boeing-737-600"), flight_LH_1234)
+
+ # With 2 free seats
+ self.test_support.with_free_seats(2, flight_LH_1234)
+
+ # Given a passenger John Doe
+ passenger_John_Doe = self.test_support.given_a_passenger(u("John"), u("Doe"))
+
+ # Book seat for John Doe at LH-1234
+ operationStatus_John_Doe_LH_1234 = self.test_support.book_seat_for(u("John"), u("Doe"), u("LH-1234"))
+
+ # Assume a valid ticket is issued
+ self.test_support.assume_valid_ticket(operationStatus_John_Doe_LH_1234)
+
+ # Cancel seat for John Doe at LH-1234
+ operationStatus_John_Doe_LH_12340 = self.test_support.cancel_seat_for(u("John"), u("Doe"), u("LH-1234"))
+
+ # Assume a valid ticket is issued
+ self.test_support.assume_valid_ticket(operationStatus_John_Doe_LH_12340)
+
+ # Cancel seat for John Doe at LH-1234
+ operationStatus_John_Doe_LH_12341 = self.test_support.cancel_seat_for(u("John"), u("Doe"), u("LH-1234"))
+
+ # Assume no valid ticket is issued
+ self.test_support.assume_no_valid_ticked_is_issued(operationStatus_John_Doe_LH_12341)
+
+
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
diff --git a/test/scenarios/overbook_seat_number.natspec b/test/scenarios/overbook_seat_number.natspec
new file mode 100644
index 0000000..3709f1c
--- /dev/null
+++ b/test/scenarios/overbook_seat_number.natspec
@@ -0,0 +1,21 @@
+Given an airplane Boeing-737-600
+
+Given a flight LH-1234
+ that is executed using a Boeing-737-600
+ with 2 free seats
+
+Given a passenger John Doe
+
+// first passenger
+Book seat for John Doe at LH-1234
+ Assume a valid ticket is issued
+
+// second passenger
+Given a passenger Jane Doe
+ Book seat for Jane Doe at LH-1234
+ Assume a valid ticket is issued
+
+// third passenger
+Given a passenger Jim Doe
+ Book seat for Jim Doe at LH-1234
+ Assume no valid ticket is issued
\ No newline at end of file
diff --git a/test/scenarios/overbook_seat_number.py b/test/scenarios/overbook_seat_number.py
new file mode 100644
index 0000000..95d1b9b
--- /dev/null
+++ b/test/scenarios/overbook_seat_number.py
@@ -0,0 +1,72 @@
+from natspec_utils.stringutils import stringToUnicode as u;
+
+import unittest
+from test.support import TestSupport
+from service.airline_service import AirlineService
+from persistence.in_memory_context import InMemoryPersistenceContext
+
+class OverbookSeatNumber(unittest.TestCase):
+ """This class serves as a template for all classes that are generated for
+ NatSpec scenarios (.natspec files). It is recognized by NatSpec based on its
+ special name and applies to all scenarios in the same package and all sub
+ packages (unless there is another template class in one of the sub packages).
+ This particular template is a unittest test case where the concrete steps of the
+ test are filled by the NatSpec code generator.
+ """
+
+ def setUp(self):
+ """Sets up the test environment (i.e., initialize the service class, the
+ entity manager and the test support class).
+ """
+ self.service = AirlineService()
+ self.persistence_context = InMemoryPersistenceContext()
+ self.test_support = TestSupport(self.service, self.persistence_context, self)
+
+ def test(self):
+ """
+ The code in this method is generated from: /de.devboost.natspec.example.python/test/scenarios/overbook_seat_number.natspec
+ Never change this method or any contents of this file, all local changes will we overwritten.
+ """
+ # Given an airplane Boeing-737-600
+ airplaneType_Boeing_737_600 = self.test_support.given_an_airplane(u("Boeing-737-600"))
+
+ # Given a flight LH-1234
+ flight_LH_1234 = self.test_support.given_a_flight(u("LH-1234"))
+
+ # that is executed using a Boeing-737-600
+ self.test_support.that_is_executed_using_a(u("Boeing-737-600"), flight_LH_1234)
+
+ # with 2 free seats
+ self.test_support.with_free_seats(2, flight_LH_1234)
+
+ # Given a passenger John Doe
+ passenger_John_Doe = self.test_support.given_a_passenger(u("John"), u("Doe"))
+
+ # Book seat for John Doe at LH-1234
+ operationStatus_John_Doe_LH_1234 = self.test_support.book_seat_for(u("John"), u("Doe"), u("LH-1234"))
+
+ # Assume a valid ticket is issued
+ self.test_support.assume_valid_ticket(operationStatus_John_Doe_LH_1234)
+
+ # Given a passenger Jane Doe
+ passenger_Jane_Doe = self.test_support.given_a_passenger(u("Jane"), u("Doe"))
+
+ # Book seat for Jane Doe at LH-1234
+ operationStatus_Jane_Doe_LH_1234 = self.test_support.book_seat_for(u("Jane"), u("Doe"), u("LH-1234"))
+
+ # Assume a valid ticket is issued
+ self.test_support.assume_valid_ticket(operationStatus_Jane_Doe_LH_1234)
+
+ # Given a passenger Jim Doe
+ passenger_Jim_Doe = self.test_support.given_a_passenger(u("Jim"), u("Doe"))
+
+ # Book seat for Jim Doe at LH-1234
+ operationStatus_Jim_Doe_LH_1234 = self.test_support.book_seat_for(u("Jim"), u("Doe"), u("LH-1234"))
+
+ # Assume no valid ticket is issued
+ self.test_support.assume_no_valid_ticked_is_issued(operationStatus_Jim_Doe_LH_1234)
+
+
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
diff --git a/test/support.py b/test/support.py
new file mode 100644
index 0000000..3aaad00
--- /dev/null
+++ b/test/support.py
@@ -0,0 +1,141 @@
+from natspec_utils.decorators import TextSyntax
+
+
+class TestSupport(object):
+ """This class contains all test support methods that are required to make the
+ example specifications executable. Methods that are decorated with the
+ TextSyntax decorator are recognized by NatSpec.
+ This class is parameterized by two parameters that are passed to the
+ constructor (the service class which implements the business logic and the
+ entity manager that provides access to all entities).
+ """
+
+ def __init__(self, service, persistence_context, test_case):
+ """Creates a new {@link TestSupport} instance. This constructor is usually
+ invoked from a {@link _NatSpecTemplate}.
+ :param service: the business service logic.
+ :param persistence_context: the entity manager to access entities.
+ :param test_case: the test case we are running, needed to access asserts
+ """
+ self.service = service
+ self.persistence_context = persistence_context
+ self.test_case = test_case
+ self.passengers = {}
+ self.flights = {}
+ self.airplane_types = {}
+
+ @TextSyntax(["Given a Passenger #1 #2"], types=["str", "str"], return_type="Passenger")
+ def given_a_passenger(self, first_name, last_name):
+ """Creates a new passenger.
+ :param first_name: the first name of the passenger.
+ :param last_name: the last name of the passenger.
+ :returns: the newly created passenger.
+ """
+ passenger = self.persistence_context.create_passenger(first_name, last_name)
+ self.passengers.update({"{0} {1}".format(first_name, last_name): passenger})
+ return passenger
+
+ @TextSyntax("With age of #2 years", types=["Passenger", "int"])
+ def with_age_of_years(self, passenger, age):
+ """Sets the age of the given passenger. The passenger is expected to be
+ contained in the implicit context (i.e., it must be created by a previous
+ sentence/test support method). The name of the passenger is not
+ explicitly required here, because there is no placeholder for the
+ passenger parameter (i.e., #1 is missing).
+ :param passenger: the passenger to set the age for.
+ :param age: the new age for the passenger.
+ """
+ passenger.age = age
+
+ @TextSyntax(["Given an Airplane #1"], types=["str"], return_type="AirplaneType")
+ def given_an_airplane(self, name):
+ """Creates a new type of airplane.
+ :param name: the name of the type of airplane.
+ :returns: the newly created airplane type.
+ """
+ airplane_type = self.persistence_context.create_airplane_type(name)
+ self.airplane_types.update({name: airplane_type})
+ return airplane_type
+
+ @TextSyntax(["Given a flight #1"], types=["str", ], return_type="Flight")
+ def given_a_flight(self, name):
+ """Creates a new flight.
+ :param name: the name of the flight.
+ :returns: the newly created flight.
+ """
+ flight = self.persistence_context.create_flight(name)
+ self.flights.update({name: flight})
+ return flight
+
+ @TextSyntax("that is executed using a #1", types=["str", "Flight"])
+ def that_is_executed_using_a(self, airplane_name, flight):
+ """Assigns the type of airplane that is used to execute the last mentioned flight.
+ :param airplane_name: the type of airplane to assign to the flight.
+ :param flight: the flight for which to set the airplane type (must be available from context).
+ """
+ airplane = self.airplane_types.get(airplane_name)
+ flight.airplane = airplane
+
+ @TextSyntax("With #1 free seats", types=["int", "Flight"])
+ def with_free_seats(self, free_seats, flight):
+ """Sets the number of free seats for the flight mentioned last.
+ :param free_seats: the number of free seats
+ :param flight: the flight to set the seats for (must be available from context).
+ """
+ flight.free_seats = free_seats
+
+ @TextSyntax("Book seat for #1 #2 at #3", types=["str", "str", "str"], return_type="OperationStatus")
+ def book_seat_for(self, first_name, last_name, flight_name):
+ """Tries to book a seat for the given passenger on the given flight.
+ :param first_name: the first name of passenger to book the flight for
+ :param last_name: the last name of passenger to book the flight for
+ :param flight_name: the name of flight to book the seat on.
+ :returns: the status of the booking operation which can be validated using
+ assume_valid_ticket(OperationStatus) or
+ assume_no_valid_ticked_is_issued(OperationStatus).
+ """
+ passenger = self.passengers.get("{0} {1}".format(first_name, last_name))
+ flight = self.flights.get(flight_name)
+ return self.service.book_seat(passenger, flight)
+
+ @TextSyntax("Cancel seat for #1 #2 at #3", types=["str", "str", "str"], return_type="OperationStatus")
+ def cancel_seat_for(self, first_name, last_name, flight_name):
+ """Tries to cancel the given passenger on the given flight.
+ :param first_name: the first name of passenger to book the flight for
+ :param last_name: the last name of passenger to book the flight for
+ :param flight_name: the name of flight to book the seat on.
+ :returns: the status of the cancel operation which can be validated using
+ assume_valid_ticket(OperationStatus) or
+ assume_no_valid_ticked_is_issued(OperationStatus).
+ """
+ passenger = self.passengers.get("{0} {1}".format(first_name, last_name))
+ flight = self.flights.get("{0}".format(flight_name))
+ return self.service.cancel_seat(passenger, flight)
+
+ @TextSyntax(["Assume a valid ticket is issued", "Assume cancellation successful"], types=["OperationStatus"])
+ def assume_valid_ticket(self, status):
+ """Checks that the validity of the last operation is True
+ (i.e., that the operation was successful). This method has a TextSyntax decorator
+ with multiple patterns (first arg) to map multiple sentences to this method.
+ :param status: the status of the last operation (must be implicitly available from context).
+ """
+ self.test_case.assertTrue(status.valid, msg=status.msg)
+
+ @TextSyntax("Assume no valid ticket is issued", types=["OperationStatus"])
+ def assume_no_valid_ticked_is_issued(self, status):
+ """Checks that the validity of the last executed business operations is False.
+ :param status: the status of the last operation (implicit parameter, not explicitly mentioned in sentence)
+ """
+ self.test_case.assertFalse(status.valid, msg=status.msg)
+
+
+ @TextSyntax("Assume #1 has passenger #2", types=["Flight", "Passenger"])
+ def assume_has_passenger(self, flight, passenger):
+ """Checks that the given passenger is booked for the given flight. Both the
+ flight and the passenger must be referenced explicitly.
+ :param flight: the flight to check
+ :param passenger: the passenger to check
+ """
+ self.test_case.assertTrue(flight.has_passenger(passenger))
+
+