From 68cad650ffcefdcd996526ca3fe111bd51d9d3cd Mon Sep 17 00:00:00 2001 From: Max Steel Date: Fri, 19 Oct 2018 10:34:16 +0200 Subject: [PATCH 01/14] Task 1a: Impl. mul test case --- app/tests/unit/test_logic.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/tests/unit/test_logic.py b/app/tests/unit/test_logic.py index 9d8c6bc..b2f2d6f 100644 --- a/app/tests/unit/test_logic.py +++ b/app/tests/unit/test_logic.py @@ -4,7 +4,8 @@ class CalculatorTests(TestCase): def test_mul(self): - pass + calculator = Calculator() + assert calculator.mul(5,10) == 50 def test_div(self): pass From 4b1dcd38492af459a87e4806a2073adacbc478f0 Mon Sep 17 00:00:00 2001 From: Max Steel Date: Fri, 19 Oct 2018 10:38:28 +0200 Subject: [PATCH 02/14] move COPY to make build more efficient --- Dockerfile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 571ee2c..0ba50ae 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,14 @@ FROM python:2 AS builder # Install the required python packages WORKDIR /app/ -# Copy flask app source code to the /app dir on the container -COPY app/ . +# Copy requirements files to the container +COPY app/*requirements.txt ./ # Install the required python packages RUN pip install \ --no-cache-dir \ -r dev-requirements.txt # Copy flask app source code to the /app dir on the container +COPY app/ . FROM builder AS unit-tester RUN py.test ./tests/unit -v \ From 2d6fc154afe35c3e2b52e57e19d04aea0941725d Mon Sep 17 00:00:00 2001 From: Max Steel Date: Fri, 19 Oct 2018 10:39:24 +0200 Subject: [PATCH 03/14] Task 1b: Impl. mul function in logic.py --- app/calculator/logic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/calculator/logic.py b/app/calculator/logic.py index a4bd1db..170f3ae 100644 --- a/app/calculator/logic.py +++ b/app/calculator/logic.py @@ -15,7 +15,7 @@ def __init__(self, min_value=-1000, max_value=1000): self.max_value = max_value def mul(self, a, b): - pass + return a*b def div(self, a, b): pass From abf1a02fa1522cb407fbe9d19ed2c118f78a726b Mon Sep 17 00:00:00 2001 From: Max Steel Date: Fri, 19 Oct 2018 10:41:49 +0200 Subject: [PATCH 04/14] Task 2: Impl. better mul tests --- app/tests/unit/test_logic.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app/tests/unit/test_logic.py b/app/tests/unit/test_logic.py index b2f2d6f..145af25 100644 --- a/app/tests/unit/test_logic.py +++ b/app/tests/unit/test_logic.py @@ -3,9 +3,17 @@ class CalculatorTests(TestCase): - def test_mul(self): + def test_mul_with_two_positive_numbers(self): calculator = Calculator() assert calculator.mul(5,10) == 50 + def test_mul_with_two_negative_numbers(self): + calculator = Calculator() + assert calculator.mul(-5,-10) == 50 + + def test_mul_with_one_negative_one_positive(self): + calculator = Calculator() + assert calculator.mul(-5,10) == -50 + def test_div(self): pass From 1bd4cebcd0b2b6c32cd3e569d72ca9a4c225d8d8 Mon Sep 17 00:00:00 2001 From: Max Steel Date: Fri, 19 Oct 2018 10:47:12 +0200 Subject: [PATCH 05/14] Task 3a: Create Test if raise exception --- app/tests/unit/test_logic.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/tests/unit/test_logic.py b/app/tests/unit/test_logic.py index 145af25..e28aea4 100644 --- a/app/tests/unit/test_logic.py +++ b/app/tests/unit/test_logic.py @@ -1,3 +1,4 @@ +import pytest from unittest import TestCase from calculator.logic import Calculator @@ -15,5 +16,9 @@ def test_mul_with_one_negative_one_positive(self): calculator = Calculator() assert calculator.mul(-5,10) == -50 + def test_calculator_throws_e_when_out_of_bounds(self): + with pytest.raises(Exception) as e_info: + calculator = Calculator(-1001,100) + def test_div(self): pass From 3cc7e810e63249e52aa290d02a3d201a20ba1ddb Mon Sep 17 00:00:00 2001 From: Max Steel Date: Fri, 19 Oct 2018 10:52:55 +0200 Subject: [PATCH 06/14] Task 3b: Impl. calulator __init__ to raise exception on OOB --- app/calculator/logic.py | 2 ++ app/tests/unit/test_logic.py | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/calculator/logic.py b/app/calculator/logic.py index 170f3ae..4b3b5b7 100644 --- a/app/calculator/logic.py +++ b/app/calculator/logic.py @@ -11,6 +11,8 @@ class ValueTooHighException(Exception): class Calculator(object): def __init__(self, min_value=-1000, max_value=1000): + if (min_value < -1000 or max_value > 1000): + raise Exception('Out of bounds min/max values used') self.min_value = min_value self.max_value = max_value diff --git a/app/tests/unit/test_logic.py b/app/tests/unit/test_logic.py index e28aea4..102dacf 100644 --- a/app/tests/unit/test_logic.py +++ b/app/tests/unit/test_logic.py @@ -17,8 +17,8 @@ def test_mul_with_one_negative_one_positive(self): assert calculator.mul(-5,10) == -50 def test_calculator_throws_e_when_out_of_bounds(self): - with pytest.raises(Exception) as e_info: - calculator = Calculator(-1001,100) + with pytest.raises(Exception): + Calculator(-1001,100) def test_div(self): pass From 7e7ebc73c470b80cc5066aacdb9625cefb0cbb5b Mon Sep 17 00:00:00 2001 From: Max Steel Date: Fri, 19 Oct 2018 10:54:16 +0200 Subject: [PATCH 07/14] Task 3c: more test cases for OOB values --- app/tests/unit/test_logic.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/tests/unit/test_logic.py b/app/tests/unit/test_logic.py index 102dacf..300ca6f 100644 --- a/app/tests/unit/test_logic.py +++ b/app/tests/unit/test_logic.py @@ -16,9 +16,13 @@ def test_mul_with_one_negative_one_positive(self): calculator = Calculator() assert calculator.mul(-5,10) == -50 - def test_calculator_throws_e_when_out_of_bounds(self): + def test_calculator_throws_e_when_out_of_bounds_low(self): with pytest.raises(Exception): Calculator(-1001,100) + def test_calculator_throws_e_when_out_of_bounds_high(self): + with pytest.raises(Exception): + Calculator(-10,1001) + def test_div(self): pass From 33e0d3696d05427e445645e3f23ccca3c03d4bb4 Mon Sep 17 00:00:00 2001 From: Max Steel Date: Fri, 19 Oct 2018 11:04:45 +0200 Subject: [PATCH 08/14] Task 4: More test cases for constructor --- app/tests/unit/test_logic.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/tests/unit/test_logic.py b/app/tests/unit/test_logic.py index 300ca6f..03cf3e7 100644 --- a/app/tests/unit/test_logic.py +++ b/app/tests/unit/test_logic.py @@ -24,5 +24,8 @@ def test_calculator_throws_e_when_out_of_bounds_high(self): with pytest.raises(Exception): Calculator(-10,1001) + def test_calculator_not_throw_e_when_in_bounds(self): + Calculator(-10,10) + def test_div(self): pass From 360084d50771216dc4a0cc31e6f490a3751d67bd Mon Sep 17 00:00:00 2001 From: Max Steel Date: Fri, 19 Oct 2018 11:32:59 +0200 Subject: [PATCH 09/14] Task 5: Division logic & tests --- app/calculator/logic.py | 2 +- app/tests/unit/test_logic.py | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/app/calculator/logic.py b/app/calculator/logic.py index 4b3b5b7..98ffb7a 100644 --- a/app/calculator/logic.py +++ b/app/calculator/logic.py @@ -20,4 +20,4 @@ def mul(self, a, b): return a*b def div(self, a, b): - pass + return a/b diff --git a/app/tests/unit/test_logic.py b/app/tests/unit/test_logic.py index 03cf3e7..0d391e6 100644 --- a/app/tests/unit/test_logic.py +++ b/app/tests/unit/test_logic.py @@ -27,5 +27,14 @@ def test_calculator_throws_e_when_out_of_bounds_high(self): def test_calculator_not_throw_e_when_in_bounds(self): Calculator(-10,10) - def test_div(self): - pass + def test_div_with_two_positive(self): + calculator = Calculator() + assert calculator.div(10,5) == 2 + + def test_div_with_two_negative(self): + calculator = Calculator() + assert calculator.div(-10,-5) == 2 + + def test_div_with_one_negative_one_positive(self): + calculator = Calculator() + assert calculator.div(-10,5) == -2 From 675351c13f6dd016b806a02af2d52a3847e0df14 Mon Sep 17 00:00:00 2001 From: Max Steel Date: Fri, 19 Oct 2018 11:34:43 +0200 Subject: [PATCH 10/14] Task 6: Impl. Divide By Zero test --- app/tests/unit/test_logic.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/tests/unit/test_logic.py b/app/tests/unit/test_logic.py index 0d391e6..cc2413a 100644 --- a/app/tests/unit/test_logic.py +++ b/app/tests/unit/test_logic.py @@ -38,3 +38,8 @@ def test_div_with_two_negative(self): def test_div_with_one_negative_one_positive(self): calculator = Calculator() assert calculator.div(-10,5) == -2 + + def test_div_by_zero_raises_e(self): + with pytest.raises(ZeroDivisionError): + calculator = Calculator() + calculator.div(10,0) From 17869dccbf09548c1f27c02920e587c0ea741aed Mon Sep 17 00:00:00 2001 From: Max Steel Date: Fri, 19 Oct 2018 11:56:47 +0200 Subject: [PATCH 11/14] refactor unit tests --- app/calculator/logic.py | 8 ++++++-- app/tests/unit/test_logic.py | 13 ++++++------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/app/calculator/logic.py b/app/calculator/logic.py index 98ffb7a..e30f354 100644 --- a/app/calculator/logic.py +++ b/app/calculator/logic.py @@ -11,13 +11,17 @@ class ValueTooHighException(Exception): class Calculator(object): def __init__(self, min_value=-1000, max_value=1000): - if (min_value < -1000 or max_value > 1000): - raise Exception('Out of bounds min/max values used') self.min_value = min_value self.max_value = max_value def mul(self, a, b): + if (a < self.min_value or a > self.max_value or b < self.min_value or b > self.max_value): + raise ValueError('Out of bounds min/max values used. Values should be >= ' + + str(self.min_value) + ' and <= ' + str(self.max_value)) return a*b def div(self, a, b): + if (a < self.min_value or a > self.max_value or b < self.min_value or b > self.max_value): + raise ValueError('Out of bounds min/max values used. Values should be >= ' + + str(self.min_value) + ' and <= ' + str(self.max_value)) return a/b diff --git a/app/tests/unit/test_logic.py b/app/tests/unit/test_logic.py index cc2413a..dc50bc5 100644 --- a/app/tests/unit/test_logic.py +++ b/app/tests/unit/test_logic.py @@ -17,15 +17,14 @@ def test_mul_with_one_negative_one_positive(self): assert calculator.mul(-5,10) == -50 def test_calculator_throws_e_when_out_of_bounds_low(self): - with pytest.raises(Exception): - Calculator(-1001,100) + with pytest.raises(ValueError): + calculator = Calculator() + calculator.mul(-1001,100) def test_calculator_throws_e_when_out_of_bounds_high(self): - with pytest.raises(Exception): - Calculator(-10,1001) - - def test_calculator_not_throw_e_when_in_bounds(self): - Calculator(-10,10) + with pytest.raises(ValueError): + calculator = Calculator() + calculator.mul(-10,1001) def test_div_with_two_positive(self): calculator = Calculator() From aac5715e56b39f4ac0b0d1f40e23236f6d43c69e Mon Sep 17 00:00:00 2001 From: Max Steel Date: Fri, 19 Oct 2018 11:57:23 +0200 Subject: [PATCH 12/14] Integration Tests Task 1 --- app/calculator/app.py | 7 +++++-- app/tests/integration/test_views.py | 12 ++++++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/app/calculator/app.py b/app/calculator/app.py index 751c3ad..b38c6c0 100644 --- a/app/calculator/app.py +++ b/app/calculator/app.py @@ -10,8 +10,11 @@ def multiply(a, b): c = Calculator() - result = c.mul(int(a), int(b)) - return str(result) + try: + result = c.mul(int(a), int(b)) + return str(result) + except Exception as e: + return str(e.args[0]) @app.route("/calc//") diff --git a/app/tests/integration/test_views.py b/app/tests/integration/test_views.py index a0df45b..22222f7 100644 --- a/app/tests/integration/test_views.py +++ b/app/tests/integration/test_views.py @@ -9,7 +9,11 @@ def setUp(self): self.client = TestClient(app) def test_multiply(self): - # r = self.client.get("/calc/3*10") - # self.assertEquals(r.status_code, 200) - # self.assertEquals(r.body, "30") - pass + r = self.client.get("/calc/3*10") + self.assertEquals(r.status_code, 200) + self.assertEquals(r.body, "30") + + def test_multiply_invalid(self): + r = self.client.get("/calc/1001*10") + self.assertEquals(r.status_code, 200) + self.assertEquals(r.body, "Out of bounds min/max values used. Values should be >= -1000 and <= 1000") From 572a24364e07af76f0e29db8235fed67b1ac6470 Mon Sep 17 00:00:00 2001 From: Max Steel Date: Fri, 19 Oct 2018 12:04:48 +0200 Subject: [PATCH 13/14] Integration Tests Task 1 --- app/calculator/app.py | 2 +- app/tests/integration/test_views.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/calculator/app.py b/app/calculator/app.py index b38c6c0..e95faad 100644 --- a/app/calculator/app.py +++ b/app/calculator/app.py @@ -14,7 +14,7 @@ def multiply(a, b): result = c.mul(int(a), int(b)) return str(result) except Exception as e: - return str(e.args[0]) + return str(e.args[0]), 403 @app.route("/calc//") diff --git a/app/tests/integration/test_views.py b/app/tests/integration/test_views.py index 22222f7..167afd4 100644 --- a/app/tests/integration/test_views.py +++ b/app/tests/integration/test_views.py @@ -15,5 +15,5 @@ def test_multiply(self): def test_multiply_invalid(self): r = self.client.get("/calc/1001*10") - self.assertEquals(r.status_code, 200) + self.assertEquals(r.status_code, 403) self.assertEquals(r.body, "Out of bounds min/max values used. Values should be >= -1000 and <= 1000") From 3bbe024e9e8bb0cc378156bb9696ede06a07f72f Mon Sep 17 00:00:00 2001 From: Max Steel Date: Fri, 19 Oct 2018 12:13:30 +0200 Subject: [PATCH 14/14] Integration Tests: Tasks 2 & 3 --- app/calculator/app.py | 10 +++++++++- app/tests/integration/test_views.py | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/app/calculator/app.py b/app/calculator/app.py index e95faad..856bdfe 100644 --- a/app/calculator/app.py +++ b/app/calculator/app.py @@ -19,7 +19,15 @@ def multiply(a, b): @app.route("/calc//") def divide(a, b): - return "Unsupported operation", 501 + c = Calculator() + + try: + result = c.div(int(a), int(b)) + return str(result) + except ValueError as e: + return str(e.args[0]), 403 + except ZeroDivisionError as e: + return 'Divide by Zero error.', 403 @app.route("/") diff --git a/app/tests/integration/test_views.py b/app/tests/integration/test_views.py index 167afd4..e852f0d 100644 --- a/app/tests/integration/test_views.py +++ b/app/tests/integration/test_views.py @@ -17,3 +17,18 @@ def test_multiply_invalid(self): r = self.client.get("/calc/1001*10") self.assertEquals(r.status_code, 403) self.assertEquals(r.body, "Out of bounds min/max values used. Values should be >= -1000 and <= 1000") + + def test_divide(self): + r = self.client.get("/calc/30/10") + self.assertEquals(r.status_code, 200) + self.assertEquals(r.body, "3") + + def test_divide_invalid(self): + r = self.client.get("/calc/-1010/10") + self.assertEquals(r.status_code, 403) + self.assertEquals(r.body, "Out of bounds min/max values used. Values should be >= -1000 and <= 1000") + + def test_divide_by_zero(self): + r = self.client.get("/calc/10/0") + self.assertEquals(r.status_code, 403) + self.assertEquals(r.body, "Divide by Zero error.") \ No newline at end of file