From bf5b0d9cece87ea998e3573ec4de8a844da4455b Mon Sep 17 00:00:00 2001 From: NicoSimoski <128238379+NicoSimoski@users.noreply.github.com> Date: Wed, 26 Jul 2023 17:17:59 +0200 Subject: [PATCH 1/4] Added implementation in common lisp with unit-test - added the existing implementation in common lisp with system-definition - added a parachute-unit-test - added a description for setup and running the unit-tests - added a description for stubbing and mocking with cl-mock --- common-lisp-parachute/README.md | 79 +++++++++++ common-lisp-parachute/gilded-rose.asd | 20 +++ common-lisp-parachute/source/gilded-rose.lisp | 128 ++++++++++++++++++ common-lisp-parachute/source/package.lisp | 14 ++ common-lisp-parachute/tests/package.lisp | 12 ++ common-lisp-parachute/tests/tests.lisp | 12 ++ 6 files changed, 265 insertions(+) create mode 100644 common-lisp-parachute/README.md create mode 100644 common-lisp-parachute/gilded-rose.asd create mode 100644 common-lisp-parachute/source/gilded-rose.lisp create mode 100644 common-lisp-parachute/source/package.lisp create mode 100644 common-lisp-parachute/tests/package.lisp create mode 100644 common-lisp-parachute/tests/tests.lisp diff --git a/common-lisp-parachute/README.md b/common-lisp-parachute/README.md new file mode 100644 index 00000000..9c542d3b --- /dev/null +++ b/common-lisp-parachute/README.md @@ -0,0 +1,79 @@ +# gilded-rose + +## Setup + +### Install quicklisp + +To run this project install quicklisp (if not already done): + - download https://beta.quicklisp.org/quicklisp.lisp + - load it with your common lisp implementation. The example with sbcl: + > sbcl --load quicklisp.lisp + - run the command + > (quicklisp-quickstart:install) + in your common lisp implementation + - run the command + > (ql:add-to-init-file) + in your common lisp implementation + +### Install project +Copy the project-folder containing this file into /quicklisp/local-projects/ that has been created when installing quicklisp. +This is the root directory for quicklisp to search for the gilded-rose.asd file which defines the system (project) and its dependencies. +The quicklisp-folder is usually created in your home-directory. + +### Work with the project + +Now you can load the project with +> (ql:quickload "gilded-rose") +in your common lisp-implementation and run the tests with +> (asdf:test-system "gilded-rose") +. + +You can stub and mock functions and methods with the cl-mock-library which is already included in the system definition of the test-system: + +(with-mocks () + (answer (call-previous)) + ( ) + (is (invocations '))) + +## Documentation + +Hi and welcome to team Gilded Rose. As you know, we are a small inn +with a prime location in a prominent city ran by a friendly +innkeeper named Allison. We also buy and sell only the finest goods. +Unfortunately, our goods are constantly degrading in quality as they +approach their sell by date. We have a system in place that updates +our inventory for us. It was developed by a no-nonsense type named +Leeroy, who has moved on to new adventures. Your task is to add the +new feature to our system so that we can begin selling a new +category of items. + +First an introduction to our system: + - All items have a SellIn value which denotes the number of days we have to sell the item + - All items have a Quality value which denotes how valuable the item is + - At the end of each day our system lowers both values for every item + +Pretty simple, right? Well this is where it gets interesting: + - Once the sell by date has passed, Quality degrades twice as fast +The Quality of an item is never negative + - "Aged Brie" actually increases in Quality the older it gets + - The Quality of an item is never more than 50 + - "Sulfuras", being a legendary item, never has to be sold or decreases in Quality + - "Backstage passes", like aged brie, increases in Quality as it's + SellIn value approaches; Quality increases by 2 when there are 10 + days or less and by 3 when there are 5 days or less but Quality + drops to 0 after the concert + +We have recently signed a supplier of conjured items. This requires an update to our system: + - "Conjured" items degrade in Quality twice as fast as normal items + +Feel free to make any changes to the UpdateQuality method and add +any new code as long as everything still works correctly. However, +do not alter the Item class or Items property as those belong to the +goblin in the corner who will insta-rage and one-shot you as he +doesn't believe in shared code ownership (you can make the +UpdateQuality method and Items property static if you like, we'll +cover for you). +Just for clarification, an item can never have its Quality increase +above 50, however "Sulfuras" is a legendary item and as such its +Quality is 80 and it never alters. + diff --git a/common-lisp-parachute/gilded-rose.asd b/common-lisp-parachute/gilded-rose.asd new file mode 100644 index 00000000..5985f942 --- /dev/null +++ b/common-lisp-parachute/gilded-rose.asd @@ -0,0 +1,20 @@ +;;;; gilded-rose.asd + +(defsystem "gilded-rose" + :description "Gilded Rose is a small inn selling the finest goods." + :author "Leeroy " + :version "1.0.0" + :pathname "source/" + :components ((:file "package") + (:file "gilded-rose" :depends-on ("package"))) + :in-order-to ((test-op (test-op "gilded-rose/tests")))) + +(defsystem "gilded-rose/tests" + :description "Unit tests for gilded-rose-package" + :author "Leeroy " + :version "1.0.0" + :depends-on ("gilded-rose" "parachute" "cl-mock") + :pathname "tests/" + :components ((:file "package") + (:file "tests" :depends-on ("package"))) + :perform (test-op (o c) (symbol-call :parachute :test :gilded-rose-tests))) diff --git a/common-lisp-parachute/source/gilded-rose.lisp b/common-lisp-parachute/source/gilded-rose.lisp new file mode 100644 index 00000000..575c86a2 --- /dev/null +++ b/common-lisp-parachute/source/gilded-rose.lisp @@ -0,0 +1,128 @@ +;; Hi and welcome to team Gilded Rose. As you know, we are a small inn +;; with a prime location in a prominent city ran by a friendly +;; innkeeper named Allison. We also buy and sell only the finest goods. +;; Unfortunately, our goods are constantly degrading in quality as they +;; approach their sell by date. We have a system in place that updates +;; our inventory for us. It was developed by a no-nonsense type named +;; Leeroy, who has moved on to new adventures. Your task is to add the +;; new feature to our system so that we can begin selling a new +;; category of items. + +;; First an introduction to our system: +;; All items have a SellIn value which denotes the number of days we have to sell the item +;; All items have a Quality value which denotes how valuable the item is +;; At the end of each day our system lowers both values for every item +;; Pretty simple, right? Well this is where it gets interesting: +;; Once the sell by date has passed, Quality degrades twice as fast +;; The Quality of an item is never negative +;; "Aged Brie" actually increases in Quality the older it gets +;; The Quality of an item is never more than 50 +;; "Sulfuras", being a legendary item, never has to be sold or decreases in Quality +;; "Backstage passes", like aged brie, increases in Quality as it's +;; SellIn value approaches; Quality increases by 2 when there are 10 +;; days or less and by 3 when there are 5 days or less but Quality +;; drops to 0 after the concert + +;; We have recently signed a supplier of conjured items. This requires an update to our system: +;; "Conjured" items degrade in Quality twice as fast as normal items +;; Feel free to make any changes to the UpdateQuality method and add +;; any new code as long as everything still works correctly. However, +;; do not alter the Item class or Items property as those belong to the +;; goblin in the corner who will insta-rage and one-shot you as he +;; doesn't believe in shared code ownership (you can make the +;; UpdateQuality method and Items property static if you like, we'll +;; cover for you). +;; Just for clarification, an item can never have its Quality increase +;; above 50, however "Sulfuras" is a legendary item and as such its +;; Quality is 80 and it never alters. + +;; https://github.com/emilybache/GildedRose-Refactoring-Kata + +;; Common Lisp version: Rainer Joswig, joswig@lisp.de, 2016 +;; Minor modifications (independent of CL impl.): Manfred Bergmann, 2022 +;; Adaption to asdf: Nico Simoski, 2023 + +;;; ================================================================ +;;; Code + +(in-package :gilded-rose) + +;;; Class ITEM + +(defclass item () + ((name :initarg :name :type string) + (sell-in :initarg :sell-in :type integer) + (quality :initarg :quality :type integer))) + +(defmethod to-string ((i item)) + (with-slots (name quality sell-in) i + (format nil "~a, ~a, ~a" name sell-in quality))) + +;;; Class gilded-rose + +(defclass gilded-rose () + ((items :initarg :items))) + +(defmethod update-quality ((gr gilded-rose)) + (with-slots (items) gr + (dotimes (i (length items)) + (with-slots (name quality sell-in) + (elt items i) + (if (and (not (equalp name "Aged Brie")) + (not (equalp name "Backstage passes to a TAFKAL80ETC concert"))) + (if (> quality 0) + (if (not (equalp name "Sulfuras, Hand of Ragnaros")) + (setf quality (- quality 1)))) + (when (< quality 50) + (setf quality (+ quality 1)) + (when (equalp name "Backstage passes to a TAFKAL80ETC concert") + (if (< sell-in 11) + (if (< quality 50) + (setf quality (+ quality 1)))) + (if (< sell-in 6) + (if (< quality 50) + (setf quality (+ quality 1))))))) + + (if (not (equalp name "Sulfuras, Hand of Ragnaros")) + (setf sell-in (- sell-in 1))) + + (if (< sell-in 0) + (if (not (equalp name "Aged Brie")) + (if (not (equalp name "Backstage passes to a TAFKAL80ETC concert")) + (if (> quality 0) + (if (not (equalp name "Sulfuras, Hand of Ragnaros")) + (setf quality (- quality 1)))) + (setf quality (- quality quality))) + (if (< quality 50) + (setf quality (+ quality 1))))))))) + +;;; Example + +(defun run-gilded-rose (days) + (write-line "OMGHAI!") + (let* ((descriptions '(("+5 Dexterity Vest" 10 20) + ("Aged Brie" 2 0) + ("Elixir of the Mongoose" 5 7) + ("Sulfuras, Hand of Ragnaros" 0 80) + ("Sulfuras, Hand of Ragnaros" -1 80) + ("Backstage passes to a TAFKAL80ETC concert" 15 20) + ("Backstage passes to a TAFKAL80ETC concert" 10 49) + ("Backstage passes to a TAFKAL80ETC concert" 5 49) + ;; this conjured item does not work properly yet + ("Conjured Mana Cake" 3 6))) + (items (loop :for (name sell-in quality) :in descriptions + :collect (make-instance 'item + :name name + :sell-in sell-in + :quality quality))) + (app (make-instance 'gilded-rose :items items))) + (dotimes (i days) + (format t "-------- day ~a --------~%" i) + (format t "name, sell-in, quality~%") + (dolist (item items) + (write-line (to-string item))) + (terpri) + (update-quality app)))) + +;;; ================================================================ +;;; EOF diff --git a/common-lisp-parachute/source/package.lisp b/common-lisp-parachute/source/package.lisp new file mode 100644 index 00000000..c94fed86 --- /dev/null +++ b/common-lisp-parachute/source/package.lisp @@ -0,0 +1,14 @@ +;;;; package.lisp + +(defpackage :gilded-rose + (:use :cl) + (:export :run-gilded-rose + :gilded-rose + :update-quality + :items + :item + :name + :sell-in + :quality)) + + diff --git a/common-lisp-parachute/tests/package.lisp b/common-lisp-parachute/tests/package.lisp new file mode 100644 index 00000000..ae158148 --- /dev/null +++ b/common-lisp-parachute/tests/package.lisp @@ -0,0 +1,12 @@ +;;;; package.lisp + +(defpackage :gilded-rose-tests + (:use :cl :gilded-rose) + (:import-from :parachute + :define-test + :is) + (:import-from :cl-mock + :with-mocks + :answer + :call-previous + :invocations)) diff --git a/common-lisp-parachute/tests/tests.lisp b/common-lisp-parachute/tests/tests.lisp new file mode 100644 index 00000000..d1752acf --- /dev/null +++ b/common-lisp-parachute/tests/tests.lisp @@ -0,0 +1,12 @@ +(in-package :gilded-rose-tests) + +(define-test gilded-rose-testsuite) + +(define-test "An item in gilded-rose is updated." + :parent gilded-rose-testsuite + (let* ((an-item (make-instance 'item :name "An item" :sell-in 1 :quality 1)) + (some-items (list an-item)) + (my-app (make-instance 'gilded-rose :items some-items))) + (update-quality my-app) + (is equal (slot-value (first (slot-value my-app 'items)) 'name) "Fix me"))) + From 6ecbea14f8111bf9d77ac9176295065c7dfd5ca1 Mon Sep 17 00:00:00 2001 From: NicoSimoski <128238379+NicoSimoski@users.noreply.github.com> Date: Thu, 27 Jul 2023 11:51:07 +0200 Subject: [PATCH 2/4] Update README.md - replaced gilded rose requirements by a link to the requirements-file - added a clarification for running the tests - added a description for using cl-mock to stub a function or method - added a description for running the testtest-fixture --- common-lisp-parachute/README.md | 74 ++++++++++++--------------------- 1 file changed, 26 insertions(+), 48 deletions(-) diff --git a/common-lisp-parachute/README.md b/common-lisp-parachute/README.md index 9c542d3b..9cbf15bb 100644 --- a/common-lisp-parachute/README.md +++ b/common-lisp-parachute/README.md @@ -1,8 +1,11 @@ -# gilded-rose +# gilded rose -## Setup +The requirements of gilded rose can be found here: +https://github.com/emilybache/GildedRose-Refactoring-Kata/blob/main/GildedRoseRequirements.txt -### Install quicklisp +# Setup + +## Install quicklisp To run this project install quicklisp (if not already done): - download https://beta.quicklisp.org/quicklisp.lisp @@ -15,65 +18,40 @@ To run this project install quicklisp (if not already done): > (ql:add-to-init-file) in your common lisp implementation -### Install project +## Install project Copy the project-folder containing this file into /quicklisp/local-projects/ that has been created when installing quicklisp. This is the root directory for quicklisp to search for the gilded-rose.asd file which defines the system (project) and its dependencies. The quicklisp-folder is usually created in your home-directory. -### Work with the project +## Working with the project Now you can load the project with > (ql:quickload "gilded-rose") -in your common lisp-implementation and run the tests with +in the common lisp implementation of your choice and run the tests with > (asdf:test-system "gilded-rose") . -You can stub and mock functions and methods with the cl-mock-library which is already included in the system definition of the test-system: +If you just want to run the tests +> (asdf:test-system "gilded-rose") +is sufficient. + +You can mock functions and methods with the cl-mock-library which is already included in the system definition of the test-system: (with-mocks () (answer (call-previous)) ( ) (is (invocations '))) + +If you just want to stub functions you can replace +(call-previous) +with a return value of your choice and your test does not depend on +(invocations ') -## Documentation - -Hi and welcome to team Gilded Rose. As you know, we are a small inn -with a prime location in a prominent city ran by a friendly -innkeeper named Allison. We also buy and sell only the finest goods. -Unfortunately, our goods are constantly degrading in quality as they -approach their sell by date. We have a system in place that updates -our inventory for us. It was developed by a no-nonsense type named -Leeroy, who has moved on to new adventures. Your task is to add the -new feature to our system so that we can begin selling a new -category of items. - -First an introduction to our system: - - All items have a SellIn value which denotes the number of days we have to sell the item - - All items have a Quality value which denotes how valuable the item is - - At the end of each day our system lowers both values for every item - -Pretty simple, right? Well this is where it gets interesting: - - Once the sell by date has passed, Quality degrades twice as fast -The Quality of an item is never negative - - "Aged Brie" actually increases in Quality the older it gets - - The Quality of an item is never more than 50 - - "Sulfuras", being a legendary item, never has to be sold or decreases in Quality - - "Backstage passes", like aged brie, increases in Quality as it's - SellIn value approaches; Quality increases by 2 when there are 10 - days or less and by 3 when there are 5 days or less but Quality - drops to 0 after the concert - -We have recently signed a supplier of conjured items. This requires an update to our system: - - "Conjured" items degrade in Quality twice as fast as normal items - -Feel free to make any changes to the UpdateQuality method and add -any new code as long as everything still works correctly. However, -do not alter the Item class or Items property as those belong to the -goblin in the corner who will insta-rage and one-shot you as he -doesn't believe in shared code ownership (you can make the -UpdateQuality method and Items property static if you like, we'll -cover for you). -Just for clarification, an item can never have its Quality increase -above 50, however "Sulfuras" is a legendary item and as such its -Quality is 80 and it never alters. +## Running the texttest-fixture +If you don't want to work with the unit-tests you can test your program with the texttest-fixture. +After loading the project in the common lisp implementation of your choice with +> (ql:quickload "gilded-rose") +you can run the texttest-fixture with +> (gilded-rose::run-gilded-rose ) +where is the number of days you want to simulate. From 35f11a141d39522be7b070a50c985b0497a04964 Mon Sep 17 00:00:00 2001 From: NicoSimoski <128238379+NicoSimoski@users.noreply.github.com> Date: Thu, 27 Jul 2023 11:55:00 +0200 Subject: [PATCH 3/4] Update tests.lisp - adapted initialization and testcase to the values of the implementation in other programming languages --- common-lisp-parachute/tests/tests.lisp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common-lisp-parachute/tests/tests.lisp b/common-lisp-parachute/tests/tests.lisp index d1752acf..8cdc59a3 100644 --- a/common-lisp-parachute/tests/tests.lisp +++ b/common-lisp-parachute/tests/tests.lisp @@ -2,11 +2,11 @@ (define-test gilded-rose-testsuite) -(define-test "An item in gilded-rose is updated." +(define-test "Test foo." :parent gilded-rose-testsuite - (let* ((an-item (make-instance 'item :name "An item" :sell-in 1 :quality 1)) + (let* ((an-item (make-instance 'item :name "foo" :sell-in 0 :quality 0)) (some-items (list an-item)) (my-app (make-instance 'gilded-rose :items some-items))) (update-quality my-app) - (is equal (slot-value (first (slot-value my-app 'items)) 'name) "Fix me"))) + (is equal (slot-value (first (slot-value my-app 'items)) 'name) "fixme"))) From d464ad8d8a9cbcf16fb071263bdbfa6b8fdeed2b Mon Sep 17 00:00:00 2001 From: NicoSimoski <128238379+NicoSimoski@users.noreply.github.com> Date: Thu, 27 Jul 2023 11:55:50 +0200 Subject: [PATCH 4/4] Update gilded-rose.lisp - removed the requirements of gilded rose --- common-lisp-parachute/source/gilded-rose.lisp | 38 ------------------- 1 file changed, 38 deletions(-) diff --git a/common-lisp-parachute/source/gilded-rose.lisp b/common-lisp-parachute/source/gilded-rose.lisp index 575c86a2..9e523cc6 100644 --- a/common-lisp-parachute/source/gilded-rose.lisp +++ b/common-lisp-parachute/source/gilded-rose.lisp @@ -1,41 +1,3 @@ -;; Hi and welcome to team Gilded Rose. As you know, we are a small inn -;; with a prime location in a prominent city ran by a friendly -;; innkeeper named Allison. We also buy and sell only the finest goods. -;; Unfortunately, our goods are constantly degrading in quality as they -;; approach their sell by date. We have a system in place that updates -;; our inventory for us. It was developed by a no-nonsense type named -;; Leeroy, who has moved on to new adventures. Your task is to add the -;; new feature to our system so that we can begin selling a new -;; category of items. - -;; First an introduction to our system: -;; All items have a SellIn value which denotes the number of days we have to sell the item -;; All items have a Quality value which denotes how valuable the item is -;; At the end of each day our system lowers both values for every item -;; Pretty simple, right? Well this is where it gets interesting: -;; Once the sell by date has passed, Quality degrades twice as fast -;; The Quality of an item is never negative -;; "Aged Brie" actually increases in Quality the older it gets -;; The Quality of an item is never more than 50 -;; "Sulfuras", being a legendary item, never has to be sold or decreases in Quality -;; "Backstage passes", like aged brie, increases in Quality as it's -;; SellIn value approaches; Quality increases by 2 when there are 10 -;; days or less and by 3 when there are 5 days or less but Quality -;; drops to 0 after the concert - -;; We have recently signed a supplier of conjured items. This requires an update to our system: -;; "Conjured" items degrade in Quality twice as fast as normal items -;; Feel free to make any changes to the UpdateQuality method and add -;; any new code as long as everything still works correctly. However, -;; do not alter the Item class or Items property as those belong to the -;; goblin in the corner who will insta-rage and one-shot you as he -;; doesn't believe in shared code ownership (you can make the -;; UpdateQuality method and Items property static if you like, we'll -;; cover for you). -;; Just for clarification, an item can never have its Quality increase -;; above 50, however "Sulfuras" is a legendary item and as such its -;; Quality is 80 and it never alters. - ;; https://github.com/emilybache/GildedRose-Refactoring-Kata ;; Common Lisp version: Rainer Joswig, joswig@lisp.de, 2016