Revision: 2646
Author: janne.t.harkonen
Date: Tue Mar 16 05:36:43 2010
Log: restructured
http://code.google.com/p/robotframework/source/detail?r=2646
Added:
/trunk/proto/atdd_example/atest/lib
/trunk/proto/atdd_example/atest/lib/VacalcLibrary.py
/trunk/proto/atdd_example/src
/trunk/proto/atdd_example/src/vacalc.py
/trunk/proto/atdd_example/utest
/trunk/proto/atdd_example/utest/test_vacalc.py
Deleted:
/trunk/proto/atdd_example/VacalcLibrary.py
/trunk/proto/atdd_example/atest/add_employee.txt
/trunk/proto/atdd_example/atest/amount_of_vacation.txt
/trunk/proto/atdd_example/atest/query_amount_of_vacation.txt
/trunk/proto/atdd_example/atest/resource.txt
/trunk/proto/atdd_example/test_vacalc.py
/trunk/proto/atdd_example/vacalc.py
=======================================
--- /dev/null
+++ /trunk/proto/atdd_example/atest/lib/VacalcLibrary.py Tue Mar 16
05:36:43 2010
@@ -0,0 +1,46 @@
+import os
+import sys
+import subprocess
+import datetime
+import tempfile
+
+import vacalc
+
+
+class VacalcLibrary(object):
+
+ def __init__(self):
+ self._db_file = os.path.join(tempfile.gettempdir(),
+ 'vacalc-atestdb.csv')
+
+ def count_vacation(self, startdate, year):
+ resource = vacalc.Employee('Test Resource', startdate)
+ return vacalc.Vacation(resource.startdate, int(year)).days
+
+ def clear_database(self):
+ if os.path.isfile(self._db_file):
+ print 'Removing %s' % self._db_file
+ os.remove(self._db_file)
+
+ def add_employee(self, name, startdate):
+ self._run('add_employee', name, startdate)
+
+ def get_employee(self, name):
+ self._run('get_employee', name)
+
+ def show_vacation(self, name, year):
+ self._run('show_vacation', name, year)
+
+ def _run(self, command, *args):
+ cmd = [sys.executable, vacalc.__file__, command] + list(args)
+ print subprocess.list2cmdline(cmd)
+ proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ env={'VACALC_DB': self._db_file})
+ self._status = proc.stdout.read().strip()
+ print self._status
+
+ def status_should_be(self, status):
+ if self._status != status:
+ raise AssertionError("Expected status to be '%s' but it
was '%s'"
+ % (status, self._status))
=======================================
--- /dev/null
+++ /trunk/proto/atdd_example/src/vacalc.py Tue Mar 16 05:36:43 2010
@@ -0,0 +1,153 @@
+from __future__ import with_statement
+import os
+import sys
+import csv
+import datetime
+import tempfile
+
+
+class VacalcError(Exception): pass
+
+
+class EmployeeStore(object):
+
+ def __init__(self, db_file):
+ self._db_file = db_file
+ if self._db_file and os.path.isfile(self._db_file):
+ self._employees = self._read_employees(self._db_file)
+ else:
+ self._employees = {}
+
+ def _read_employees(self, path):
+ employees = {}
+ with open(path) as db:
+ for row in csv.reader(db):
+ employee = Employee(row[0], row[1])
+ employees[employee.name] = employee
+ return employees
+
+ def get_employee(self, name):
+ try:
+ return self._employees[name]
+ except KeyError:
+ raise VacalcError("Employee '%s' not found" % name)
+
+ def get_all_employees(self):
+ return self._employees.values()
+
+ def add_employee(self, employee):
+ if employee.name in self._employees:
+ raise VacalcError("Employee '%s' already exists in the
system" %
+ employee.name)
+ self._employees[employee.name] = employee
+ self._serialize(employee)
+
+ def _serialize(self, employee):
+ if not self._db_file:
+ return
+ with open(self._db_file, 'a') as db:
+ writer = csv.writer(db, lineterminator='\n')
+ writer.writerow([employee.name, employee.startdate])
+
+
+class Employee(object):
+
+ def __init__(self, name, startdate):
+ self.name = name
+ self.startdate = self._parse_date(startdate)
+
+ def _parse_date(self, datestring):
+ year, month, day = datestring.split('-')
+ return datetime.date(int(year), int(month), int(day))
+
+
+class Vacation(object):
+ max_vacation = 12 * 2.5
+ no_vacation = 0
+ vacation_per_month = 2
+ credit_start_month = 4
+ work_days_required= 14
+
+ def __init__(self, empstartdate, vacation_year):
+ self.days = self._calculate_vacation(empstartdate, vacation_year)
+
+ def _calculate_vacation(self, start, year):
+ if self._has_worked_longer_than_year(start, year):
+ return self.max_vacation
+ if self._started_after_holiday_credit_year_ended(start, year):
+ return self.no_vacation
+ return self._count_working_months(start) * self.vacation_per_month
+
+ def _has_worked_longer_than_year(self, start, year):
+ return year-start.year > 1 or \
+ (year-start.year == 1 and start.month <
self.credit_start_month)
+
+ def _started_after_holiday_credit_year_ended(self, start, year):
+ return start.year-year > 0 or \
+ (year == start.year and start.month >=
self.credit_start_month)
+
+ def _count_working_months(self, start):
+ months = self.credit_start_month - start.month
+ if months <= 0:
+ months += 12
+ if self._first_month_has_too_few_working_days(start):
+ months -= 1
+ return months
+
+ def _first_month_has_too_few_working_days(self, start):
+ days = 0
+ date = start
+ while date:
+ if self._is_working_day(date):
+ days += 1
+ date = self._next_date(date)
+ return days < self.work_days_required
+
+ def _is_working_day(self, date):
+ return date.weekday() < 5
+
+ def _next_date(self, date):
+ try:
+ return date.replace(day=date.day+1)
+ except ValueError:
+ return None
+
+
+class VacationCalculator(object):
+
+ def __init__(self, employeestore):
+ self._employeestore = employeestore
+
+ def show_vacation(self, name, year):
+ employee = self._employeestore.get_employee(name)
+ vacation = Vacation(employee.startdate, int(year))
+ return "%s has %d vacation days in year %s" \
+ % (name, vacation.days, year)
+
+ def add_employee(self, name, startdate):
+ employee = Employee(name, startdate)
+ self._employeestore.add_employee(employee)
+ return "Successfully added employee '%s'." % employee.name
+
+ def get_employee(self, name):
+ employee = self._employeestore.get_employee(name)
+ return '%s: start date %s' % (employee.name, employee.startdate)
+
+
+def main(args):
+ db_file = os.environ.get('VACALC_DB',
os.path.join(tempfile.gettempdir(),
+ 'vacalcdb.csv'))
+ try:
+ cmd = getattr(VacationCalculator(EmployeeStore(db_file)), args[0])
+ return cmd(*args[1:])
+ except (AttributeError, TypeError):
+ raise VacalcError('invalid command or arguments')
+
+
+if __name__ == '__main__':
+ try:
+ print main(sys.argv[1:])
+ sys.exit(0)
+ except VacalcError, err:
+ print err
+ sys.exit(1)
=======================================
--- /dev/null
+++ /trunk/proto/atdd_example/utest/test_vacalc.py Tue Mar 16 05:36:43 2010
@@ -0,0 +1,47 @@
+import datetime
+import unittest
+
+from vacalc import Employee, EmployeeStore, VacalcError, Vacation
+
+
+class TestEmployee(unittest.TestCase):
+
+ def test_creating_employee(self):
+ employee = Employee('Juan von Rantanen', '2010-3-15')
+ self.assertEquals(employee.name, 'Juan von Rantanen')
+ self.assertEquals(employee.startdate, datetime.date(2010, 3, 15))
+
+
+class TestVacation(unittest.TestCase):
+
+ def test_creating_vacation(self):
+ vacation = Vacation(datetime.date(2010, 3, 16), 2010)
+
+
+class TestEmployeeStore(unittest.TestCase):
+
+ def test_adding_employee(self):
+ store = EmployeeStore(None)
+ employee = Employee('Test Employee Store', '2000-12-24')
+ store.add_employee(employee)
+ self.assertEquals(store.get_all_employees(), [employee])
+
+ def test_adding_duplicate_employee(self):
+ store = EmployeeStore(None)
+ store.add_employee(Employee('test', '2000-12-24'))
+ self.assertRaises(VacalcError, store.add_employee,
+ Employee('test', '2001-01-24'))
+
+ def test_getting_employee(self):
+ store = EmployeeStore(None)
+ employee = Employee('Mr Foo Bar', '1990-02-03')
+ store.add_employee(employee)
+ self.assertEquals(store.get_employee('Mr Foo Bar'), employee)
+
+ def test_get_missing_employee(self):
+ store = EmployeeStore(None)
+ self.assertRaises(VacalcError, store.get_employee, 'I am not here')
+
+
+if __name__ == '__main__':
+ unittest.main()
=======================================
--- /trunk/proto/atdd_example/VacalcLibrary.py Tue Mar 16 05:06:41 2010
+++ /dev/null
@@ -1,46 +0,0 @@
-import os
-import sys
-import subprocess
-import datetime
-import tempfile
-
-from vacalc import Employee, EmployeeStore, Vacation
-
-
-class VacalcLibrary(object):
-
- def __init__(self):
- self._db_file = os.path.join(tempfile.gettempdir(),
- 'vacalc-atestdb.csv')
-
- def count_vacation(self, startdate, year):
- resource = Employee('Test Resource', startdate)
- return Vacation(resource.startdate, int(year)).days
-
- def clear_database(self):
- if os.path.isfile(self._db_file):
- print 'Removing %s' % self._db_file
- os.remove(self._db_file)
-
- def add_employee(self, name, startdate):
- self._run('add_employee', name, startdate)
-
- def get_employee(self, name):
- self._run('get_employee', name)
-
- def show_vacation(self, name, year):
- self._run('show_vacation', name, year)
-
- def _run(self, command, *args):
- cmd = [sys.executable, 'vacalc.py', command] + list(args)
- print subprocess.list2cmdline(cmd)
- proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT,
- env={'VACALC_DB': self._db_file})
- self._status = proc.stdout.read().strip()
- print self._status
-
- def status_should_be(self, status):
- if self._status != status:
- raise AssertionError("Expected status to be '%s' but it
was '%s'"
- % (status, self._status))
=======================================
--- /trunk/proto/atdd_example/atest/add_employee.txt Tue Mar 16 03:02:30
2010
+++ /dev/null
@@ -1,23 +0,0 @@
-*** Test Cases ***
-
-Add employee
- Given no users exist in the system
- When employee Janne H is added with start date 2010-1-1
- Then message "Successfully added employee 'Janne H'." is shown
-
-Added Employee is done persistently
- Given no users exist in the system
- And employee Pekka K is added with start date 2009-1-1
- When user queries info about Pekka K
- Then message "Pekka K: start date 2009-01-01" is shown
-
-Add already existing employee
- Given no users exist in the system
- And employee JR is added with start date 2009-1-1
- When employee JR is added with start date 2010-1-1
- Then error message "Employee 'JR' already exists in the system" is
shown
-
-
-*** Settings ***
-
-Resource resource.txt
=======================================
--- /trunk/proto/atdd_example/atest/amount_of_vacation.txt Tue Mar 16
03:02:30 2010
+++ /dev/null
@@ -1,37 +0,0 @@
-holiday credit year: period from 1 April to 31 March
-
-*** Test Cases ***
-Employee has started exactly a year before the holiday credit year starts
- When employee starts on 2009-4-1 then she has 24 day vacation on year
2010
-
-Employee has started day over a year before the holiday credit year starts
- When employee starts on 2009-3-31 then she has 30 day vacation on year
2010
-
-Employee has less than 14 days during the first month of employment
- Amount of vacation should be 2010-2-10 2010 2
-
-Employee has 14 days during the first month of employment
- Amount of vacation should be 2010-2-9 2010 4
-
-Employee has started during the holiday credit year
- Amount of vacation should be 2010-6-1 2010 0
-
-Employee has started after the holiday credit year
- Amount of vacation should be 2011-6-1 2010 0
-
-Employee has started more than year before the holiday credit year starts
- Amount of vacation should be 2000-1-21 2010 30
-
-
-*** Keywords ***
-When employee starts on ${startdate} then she has ${expected vacation} day
vacation on year ${year}
- Amount of vacation should be ${startdate} ${year} ${expected vacation}
-
-Amount of vacation should be
- [Arguments] ${employee startdate} ${vacation year} ${expected amount
of vacation}
- ${amount of vacation} = Count Vacation ${employee startdate}
${vacation year}
- Should Be Equal As Integers ${amount of vacation} ${expected amount of
vacation}
-
-*** Settings ***
-Resource resource.txt
-
=======================================
--- /trunk/proto/atdd_example/atest/query_amount_of_vacation.txt Tue Mar 16
03:49:19 2010
+++ /dev/null
@@ -1,22 +0,0 @@
-*** Test Cases ***
-
-Employee vacations can be queried
- Given no users exist in the system
- And employee Kari H is added with start date 2010-1-1
- When amount of vacation days for Kari H is queried for year 2010
- Then message "Kari H has 6 vacation days in year 2010" is shown
-
-Employee vacations queary fails if employee does not exist
- Given no users exist in the system
- When amount of vacation days for Kari H is queried for year 2010
- Then error message "Employee 'Kari H' not found" is shown
-
-
-*** User Keywords ***
-
-When amount of vacation days for ${name} is queried for year ${year}
- Show vacation ${name} ${year}
-
-
-*** Settings ***
-Resource resource.txt
=======================================
--- /trunk/proto/atdd_example/atest/resource.txt Tue Mar 16 05:06:37 2010
+++ /dev/null
@@ -1,22 +0,0 @@
-*** Settings ***
-
-Library VacalcLibrary
-
-
-*** User Keywords ***
-
-Given no users exist in the system
- Clear Database
-
-Then message "${msg}" is shown
- Status Should Be ${msg}
-
-Then error message "${msg}" is shown
- Status Should Be ${msg}
-
-Employee ${name} is added with start date ${date}
- Add Employee ${name} ${date}
-
-User queries info about ${name}
- Get Employee ${name}
-
=======================================
--- /trunk/proto/atdd_example/test_vacalc.py Tue Mar 16 05:06:41 2010
+++ /dev/null
@@ -1,47 +0,0 @@
-import datetime
-import unittest
-
-from vacalc import Employee, EmployeeStore, VacalcError, Vacation
-
-
-class TestEmployee(unittest.TestCase):
-
- def test_creating_employee(self):
- employee = Employee('Juan von Rantanen', '2010-3-15')
- self.assertEquals(employee.name, 'Juan von Rantanen')
- self.assertEquals(employee.startdate, datetime.date(2010, 3, 15))
-
-
-class TestVacation(unittest.TestCase):
-
- def test_creating_vacation(self):
- vacation = Vacation(datetime.date(2010, 3, 16), 2010)
-
-
-class TestEmployeeStore(unittest.TestCase):
-
- def test_adding_employee(self):
- store = EmployeeStore(None)
- employee = Employee('Test Employee Store', '2000-12-24')
- store.add_employee(employee)
- self.assertEquals(store.get_all_employees(), [employee])
-
- def test_adding_duplicate_employee(self):
- store = EmployeeStore(None)
- store.add_employee(Employee('test', '2000-12-24'))
- self.assertRaises(VacalcError, store.add_employee,
- Employee('test', '2001-01-24'))
-
- def test_getting_employee(self):
- store = EmployeeStore(None)
- employee = Employee('Mr Foo Bar', '1990-02-03')
- store.add_employee(employee)
- self.assertEquals(store.get_employee('Mr Foo Bar'), employee)
-
- def test_get_missing_employee(self):
- store = EmployeeStore(None)
- self.assertRaises(VacalcError, store.get_employee, 'I am not here')
-
-
-if __name__ == '__main__':
- unittest.main()
=======================================
--- /trunk/proto/atdd_example/vacalc.py Tue Mar 16 05:06:41 2010
+++ /dev/null
@@ -1,153 +0,0 @@
-from __future__ import with_statement
-import os
-import sys
-import csv
-import datetime
-import tempfile
-
-
-class VacalcError(Exception): pass
-
-
-class EmployeeStore(object):
-
- def __init__(self, db_file):
- self._db_file = db_file
- if self._db_file and os.path.isfile(self._db_file):
- self._employees = self._read_employees(self._db_file)
- else:
- self._employees = {}
-
- def _read_employees(self, path):
- employees = {}
- with open(path) as db:
- for row in csv.reader(db):
- employee = Employee(row[0], row[1])
- employees[employee.name] = employee
- return employees
-
- def get_employee(self, name):
- try:
- return self._employees[name]
- except KeyError:
- raise VacalcError("Employee '%s' not found" % name)
-
- def get_all_employees(self):
- return self._employees.values()
-
- def add_employee(self, employee):
- if employee.name in self._employees:
- raise VacalcError("Employee '%s' already exists in the
system" %
- employee.name)
- self._employees[employee.name] = employee
- self._serialize(employee)
-
- def _serialize(self, employee):
- if not self._db_file:
- return
- with open(self._db_file, 'a') as db:
- writer = csv.writer(db, lineterminator='\n')
- writer.writerow([employee.name, employee.startdate])
-
-
-class Employee(object):
-
- def __init__(self, name, startdate):
- self.name = name
- self.startdate = self._parse_date(startdate)
-
- def _parse_date(self, datestring):
- year, month, day = datestring.split('-')
- return datetime.date(int(year), int(month), int(day))
-
-
-class Vacation(object):
- max_vacation = 12 * 2.5
- no_vacation = 0
- vacation_per_month = 2
- credit_start_month = 4
- work_days_required= 14
-
- def __init__(self, empstartdate, vacation_year):
- self.days = self._calculate_vacation(empstartdate, vacation_year)
-
- def _calculate_vacation(self, start, year):
- if self._has_worked_longer_than_year(start, year):
- return self.max_vacation
- if self._started_after_holiday_credit_year_ended(start, year):
- return self.no_vacation
- return self._count_working_months(start) * self.vacation_per_month
-
- def _has_worked_longer_than_year(self, start, year):
- return year-start.year > 1 or \
- (year-start.year == 1 and start.month <
self.credit_start_month)
-
- def _started_after_holiday_credit_year_ended(self, start, year):
- return start.year-year > 0 or \
- (year == start.year and start.month >=
self.credit_start_month)
-
- def _count_working_months(self, start):
- months = self.credit_start_month - start.month
- if months <= 0:
- months += 12
- if self._first_month_has_too_few_working_days(start):
- months -= 1
- return months
-
- def _first_month_has_too_few_working_days(self, start):
- days = 0
- date = start
- while date:
- if self._is_working_day(date):
- days += 1
- date = self._next_date(date)
- return days < self.work_days_required
-
- def _is_working_day(self, date):
- return date.weekday() < 5
-
- def _next_date(self, date):
- try:
- return date.replace(day=date.day+1)
- except ValueError:
- return None
-
-
-class VacationCalculator(object):
-
- def __init__(self, employeestore):
- self._employeestore = employeestore
-
- def show_vacation(self, name, year):
- employee = self._employeestore.get_employee(name)
- vacation = Vacation(employee.startdate, int(year))
- return "%s has %d vacation days in year %s" \
- % (name, vacation.days, year)
-
- def add_employee(self, name, startdate):
- employee = Employee(name, startdate)
- self._employeestore.add_employee(employee)
- return "Successfully added employee '%s'." % employee.name
-
- def get_employee(self, name):
- employee = self._employeestore.get_employee(name)
- return '%s: start date %s' % (employee.name, employee.startdate)
-
-
-def main(args):
- db_file = os.environ.get('VACALC_DB',
os.path.join(tempfile.gettempdir(),
- 'vacalcdb.csv'))
- try:
- cmd = getattr(VacationCalculator(EmployeeStore(db_file)), args[0])
- return cmd(*args[1:])
- except (AttributeError, TypeError):
- raise VacalcError('invalid command or arguments')
-
-
-if __name__ == '__main__':
- try:
- print main(sys.argv[1:])
- sys.exit(0)
- except VacalcError, err:
- print err
- sys.exit(1)