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 @@
+Êþº¾ 2 4
+
+
+
+
+
+
+ ! "
+ # $
+
+ %
+ & '
+ ( ) * <init> ()V Code LineNumberTable main ([Ljava/lang/String;)V vacalcApplication 0()Lorg/robotframework/vacalc/VacationCalculator; importAppClass
+()Lorg/python/core/PyObject;
+SourceFile VacalcRunner.java + , - ,org/robotframework/vacalc/VacationCalculator . / !org/python/util/PythonInterpreter 3import
vacalc;
from vacalc import
VacalcApplication 0 1 VacalcApplication 2 3 &org/robotframework/vacalc/VacalcRunner java/lang/Object create org/python/core/PyObject __call__
+__tojava__ %(Ljava/lang/Class;)Ljava/lang/Object; exec (Ljava/lang/String;)V get .(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
+SourceFile VacationCalculator.java ,org/robotframework/vacalc/VacationCalculator java/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