Revision: 4155
Author: janne.t.harkonen
Date: Wed Sep 29 06:02:59 2010
Log: initial stuff for berlin tutorial
http://code.google.com/p/robotframework/source/detail?r=4155

Added:
 /trunk/proto/atdd-tutorial-berlin-2010
 /trunk/proto/atdd-tutorial-berlin-2010/atest
 /trunk/proto/atdd-tutorial-berlin-2010/atest/run_tests.sh
 /trunk/proto/atdd-tutorial-berlin-2010/atest/vacalc
 /trunk/proto/atdd-tutorial-berlin-2010/atest/vacalc/add_employee.txt
 /trunk/proto/atdd-tutorial-berlin-2010/atest/vacalc/start_app.txt
 /trunk/proto/atdd-tutorial-berlin-2010/bin
 /trunk/proto/atdd-tutorial-berlin-2010/bin/org
 /trunk/proto/atdd-tutorial-berlin-2010/bin/org/robotframework
 /trunk/proto/atdd-tutorial-berlin-2010/bin/org/robotframework/vacalc
/trunk/proto/atdd-tutorial-berlin-2010/bin/org/robotframework/vacalc/VacalcRunner.class /trunk/proto/atdd-tutorial-berlin-2010/bin/org/robotframework/vacalc/VacationCalculator.class
 /trunk/proto/atdd-tutorial-berlin-2010/compile.sh
 /trunk/proto/atdd-tutorial-berlin-2010/src
 /trunk/proto/atdd-tutorial-berlin-2010/src/org
 /trunk/proto/atdd-tutorial-berlin-2010/src/org/robotframework
 /trunk/proto/atdd-tutorial-berlin-2010/src/org/robotframework/vacalc
/trunk/proto/atdd-tutorial-berlin-2010/src/org/robotframework/vacalc/VacalcRunner.java /trunk/proto/atdd-tutorial-berlin-2010/src/org/robotframework/vacalc/VacationCalculator.java
 /trunk/proto/atdd-tutorial-berlin-2010/src/vacalc
 /trunk/proto/atdd-tutorial-berlin-2010/src/vacalc/__init__.py
 /trunk/proto/atdd-tutorial-berlin-2010/src/vacalc/employeestore.py
 /trunk/proto/atdd-tutorial-berlin-2010/src/vacalc/ui.py
 /trunk/proto/atdd-tutorial-berlin-2010/src/vacalc/vacalcapp.py
 /trunk/proto/atdd-tutorial-berlin-2010/start_app.sh

=======================================
--- /dev/null
+++ /trunk/proto/atdd-tutorial-berlin-2010/atest/run_tests.sh Wed Sep 29 06:02:59 2010
@@ -0,0 +1,5 @@
+ROOTDIR=`dirname $0`/..
+LIBPATH=$ROOTDIR/lib
+SRCPATH=$ROOTDIR/src
+CP=$LIBPATH/robotframework-2.5.4.jar:$LIBPATH/swinglibrary-1.1.1.jar:$ROOTDIR/bin/
+CLASSPATH=$CP java org.robotframework.RobotFramework -P $SRCPATH $*
=======================================
--- /dev/null
+++ /trunk/proto/atdd-tutorial-berlin-2010/atest/vacalc/add_employee.txt Wed Sep 29 06:02:59 2010
@@ -0,0 +1,17 @@
+***Test Cases***
+
+Adding employee
+    Given no employee "Juha" exists in the system
+    When "Juha" with start date 1.1.2010 is added
+    Then message "Employee 'Juha' was added successfully" is shown
+    and "Juha" with start date 1.1.2010 exists in the database
+
+Adding employee with same ID
+    Given employee "Juha" with start date 1.1.2010 exists in the system
+    When "Juha" with start date 2.1.2010 is added
+    Then message "Employee 'Juha' already exists in the system" is shown
+    and "Juha" with start date 1.1.2010 exists in the database
+
+***Settings***
+Force Tags   Sprint-1
+Resource  resource.txt
=======================================
--- /dev/null
+++ /trunk/proto/atdd-tutorial-berlin-2010/atest/vacalc/start_app.txt Wed Sep 29 06:02:59 2010
@@ -0,0 +1,7 @@
+* settings *
+Library  SwingLibrary
+
+* test cases *
+Test  Start Application  org.robotframework.vacalc.VacalcRunner
+    Select Window  Vacation Calculator
+    ${title}=  Get Selected Window Title
=======================================
--- /dev/null
+++ /trunk/proto/atdd-tutorial-berlin-2010/bin/org/robotframework/vacalc/VacalcRunner.class Wed Sep 29 06:02:59 2010
@@ -0,0 +1,24 @@
+Êþº¾24
+
+
+
+
+
+
+ !"
+ #$
+
+%
+&'
+()*<init>()VCodeLineNumberTablemain([Ljava/lang/String;)VvacalcApplication0()Lorg/robotframework/vacalc/VacationCalculator;importAppClass
+()Lorg/python/core/PyObject;
+SourceFileVacalcRunner.java   + , -,org/robotframework/vacalc/VacationCalculator ./!org/python/util/PythonInterpreter3import vacalc; from vacalc import VacalcApplication 01VacalcApplication 23&org/robotframework/vacalc/VacalcRunnerjava/lang/Objectcreateorg/python/core/PyObject__call__
+__tojava__%(Ljava/lang/Class;)Ljava/lang/Object;exec(Ljava/lang/String;)Vget.(Ljava/lang/String;)Lorg/python/core/PyObject;!
+*·± %     ¸¹±
+
+
+.¸¶K*¶À°
+
+5»Y·     K*
+¶*¶
+°
=======================================
--- /dev/null
+++ /trunk/proto/atdd-tutorial-berlin-2010/bin/org/robotframework/vacalc/VacationCalculator.class Wed Sep 29 06:02:59 2010
@@ -0,0 +1,2 @@
+Êþº¾2      create()V
+SourceFileVacationCalculator.java,org/robotframework/vacalc/VacationCalculatorjava/lang/Object
=======================================
--- /dev/null
+++ /trunk/proto/atdd-tutorial-berlin-2010/compile.sh Wed Sep 29 06:02:59 2010
@@ -0,0 +1,1 @@
+CLASSPATH=lib/robotframework-2.5.3.jar javac -d bin src/org/robotframework/vacalc/*java
=======================================
--- /dev/null
+++ /trunk/proto/atdd-tutorial-berlin-2010/src/org/robotframework/vacalc/VacalcRunner.java Wed Sep 29 06:02:59 2010
@@ -0,0 +1,23 @@
+package org.robotframework.vacalc;
+
+import org.python.core.PyObject;
+import org.python.util.PythonInterpreter;
+import org.robotframework.vacalc.VacationCalculator;
+
+public class VacalcRunner {
+
+    public static void main(String[] args) {
+        vacalcApplication().create();
+    }
+
+    private static VacationCalculator vacalcApplication() {
+        PyObject application = importAppClass().__call__();
+ return (VacationCalculator) application.__tojava__(VacationCalculator.class);
+    }
+
+    private static PyObject importAppClass() {
+        PythonInterpreter interpreter = new PythonInterpreter();
+ interpreter.exec("import vacalc; from vacalc import VacalcApplication");
+        return interpreter.get("VacalcApplication");
+    }
+}
=======================================
--- /dev/null
+++ /trunk/proto/atdd-tutorial-berlin-2010/src/org/robotframework/vacalc/VacationCalculator.java Wed Sep 29 06:02:59 2010
@@ -0,0 +1,5 @@
+package org.robotframework.vacalc;
+
+public interface VacationCalculator {
+    public void create();
+}
=======================================
--- /dev/null
+++ /trunk/proto/atdd-tutorial-berlin-2010/src/vacalc/__init__.py Wed Sep 29 06:02:59 2010
@@ -0,0 +1,1 @@
+from vacalcapp import VacalcApplication
=======================================
--- /dev/null
+++ /trunk/proto/atdd-tutorial-berlin-2010/src/vacalc/employeestore.py Wed Sep 29 06:02:59 2010
@@ -0,0 +1,64 @@
+from __future__ import with_statement
+import os
+import csv
+import datetime
+
+
+class VacalcError(RuntimeError): 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):
+                date = self._convert_date(row[1])
+                employee = Employee(row[0], date)
+                employees[employee.name] = employee
+        return employees
+
+    def _convert_date(self, isodate):
+        year, month, day = isodate.split('-')
+        return '%s.%s.%s' % (day, month, year)
+
+    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):
+        day, month, year = datestring.split('.')
+        return datetime.date(int(year), int(month), int(day))
=======================================
--- /dev/null
+++ /trunk/proto/atdd-tutorial-berlin-2010/src/vacalc/ui.py Wed Sep 29 06:02:59 2010
@@ -0,0 +1,102 @@
+from javax.swing import JFrame, JList, JPanel, JLabel, JTextField, JButton
+from javax.swing.event import ListSelectionListener
+from java.awt.event import ActionListener
+from java.awt import FlowLayout, GridLayout, BorderLayout
+
+from vacalc.employeestore import Employee
+
+
+class VacalcFrame(object):
+
+    def __init__(self, employees):
+        self._frame = JFrame('Vacation Calculator',
+                             defaultCloseOperation=JFrame.EXIT_ON_CLOSE)
+        self._create_ui(employees)
+        self._frame.pack()
+
+    def _create_ui(self, employees):
+        panel = JPanel(layout=FlowLayout())
+        detais_panel = JPanel(layout=BorderLayout())
+        self._employee_list = self._create_employee_list(employees)
+ detais_panel.add(self._employee_list.widget, BorderLayout.PAGE_START)
+        self._details = EmployeeDetailsPanel(employees)
+        btn = JButton('New Employee')
+ btn.addActionListener(ListenerFactory(ActionListener, self._new_employee))
+        detais_panel.add(btn, BorderLayout.PAGE_END)
+        panel.add(detais_panel)
+        panel.add(self._details.widget)
+        self._frame.setContentPane(panel)
+
+    def _create_employee_list(self, employeestore):
+        list = EmployeeList(employeestore.get_all_employees())
+        list.add_selection_listener(ListenerFactory(ListSelectionListener,
+ self._list_item_selected))
+        return list
+
+    def _list_item_selected(self, event):
+ self._details.show_employee(self._employee_list.selected_employee())
+
+    def _new_employee(self, event):
+        self._details.edit_new_employee()
+
+    def show(self):
+        self._frame.setVisible(True)
+
+
+class EmployeeList(object):
+
+    def __init__(self, employees):
+        self._employees = employees
+        data = [e.name for e in employees]
+        self._list = JList(data, preferredSize=(200, 200))
+
+    def add_selection_listener(self, listener):
+        self._list.addListSelectionListener(listener)
+
+    def selected_employee(self):
+        return self._employees[self._list.getSelectedIndex()]
+
+    @property
+    def widget(self):
+        return self._list
+
+
+class EmployeeDetailsPanel(object):
+
+    def __init__(self, employeestore):
+        self._store = employeestore
+ self._panel = JPanel(layout=BorderLayout(), preferredSize=(300, 200))
+        itempanel = JPanel(layout=GridLayout(2,2))
+        itempanel.add(JLabel(text='Name'))
+        self._name_editor = JTextField()
+        itempanel.add(self._name_editor)
+        itempanel.add(JLabel(text='Start'))
+        self._start_date_editor = JTextField()
+        itempanel.add(self._start_date_editor)
+        button = JButton('<Add>')
+        button.addActionListener(ListenerFactory(ActionListener,
+                                                 self._add_button_pushed))
+        self._panel.add(itempanel, BorderLayout.PAGE_START)
+        self._panel.add(button, BorderLayout.SOUTH)
+
+    def show_employee(self, employee):
+        self._name_editor.setText(employee.name)
+        self._start_date_editor.setText(str(employee.startdate))
+
+    def edit_new_employee(self):
+        self._name_editor.setText('')
+        self._start_date_editor.setText('')
+
+    @property
+    def widget(self):
+        return self._panel
+
+    def _add_button_pushed(self, event):
+        self._store.add_employee(Employee(self._name_editor.getText(),
+ self._start_date_editor.getText()))
+
+
+def ListenerFactory(interface, func):
+    from java.lang import Object
+    method = list(set(dir(interface)) - set(dir(Object)))[0]
+    return type('Listener', (interface,), {method: func})()
=======================================
--- /dev/null
+++ /trunk/proto/atdd-tutorial-berlin-2010/src/vacalc/vacalcapp.py Wed Sep 29 06:02:59 2010
@@ -0,0 +1,84 @@
+import os
+import tempfile
+
+from org.robotframework.vacalc import VacationCalculator
+
+from vacalc.ui import VacalcFrame
+from vacalc.employeestore import EmployeeStore, Employee
+
+
+class VacalcApplication(VacationCalculator):
+
+    def create(self):
+ db_file = os.environ.get('VACALC_DB', os.path.join(tempfile.gettempdir(),
+                                                           'vacalcdb.csv'))
+        store = EmployeeStore(db_file)
+        self._frame = VacalcFrame(store)
+        self._frame.show()
+
+
+class VacationCalculator(object):
+    max_vacation = int(12 * 2.5)
+    no_vacation = 0
+    vacation_per_month = 2
+    credit_start_month = 4
+    work_days_required= 14
+
+    def __init__(self, employeestore):
+        self._employeestore = employeestore
+
+    def show_vacation(self, name, year):
+        employee = self._employeestore.get_employee(name)
+        vacation = self._count_vacation(employee.startdate, int(year))
+        return '%s days' % vacation
+
+    def add_employee(self, name, startdate):
+        employee = Employee(name, startdate)
+        self._employeestore.add_employee(employee)
+        return "Employee '%s' was added successfully" % employee.name
+
+    def get_employee(self, name):
+        employee = self._employeestore.get_employee(name)
+        return '%s: start date %s' % (employee.name, employee.startdate)
+
+    def _count_vacation(self, startdate, year):
+        if self._has_worked_longer_than_year(startdate, year):
+            return self.max_vacation
+        if self._started_after_holiday_credit_year_ended(startdate, year):
+            return self.no_vacation
+ return self._count_working_months(startdate) * 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
+
=======================================
--- /dev/null
+++ /trunk/proto/atdd-tutorial-berlin-2010/start_app.sh Wed Sep 29 06:02:59 2010
@@ -0,0 +1,1 @@
+java -cp lib/robotframework-2.5.4.jar:bin/ -Dpython.path=src org.robotframework.vacalc.VacalcRunner

Reply via email to