diff --git a/_toc.yml b/_toc.yml
index 933ceb5..05912ef 100644
--- a/_toc.yml
+++ b/_toc.yml
@@ -14,9 +14,7 @@
- file: testgranularity/unittesting
sections:
- file: testgranularity/organization_of_unit_tests.ipynb
- - file: testgranularity/integrationtesting
- sections:
- - file: testgranularity/mocking.ipynb
+ - file: testgranularity/integrationtesting.ipynb
- file: testgranularity/systemtesting
- file: testgranularity/acceptancetesting/acceptancetesting.ipynb
diff --git a/testgranularity/driver.ipynb b/testgranularity/driver.ipynb
deleted file mode 100644
index 9440111..0000000
--- a/testgranularity/driver.ipynb
+++ /dev/null
@@ -1,131 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# A Driver example with Python"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "First we implement a common interface which has a contract of how we are going to call the lower modules under construction"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {},
- "outputs": [],
- "source": [
- "class ControllerInterface():\n",
- " def __init__(self, mailer):\n",
- " raise NotImplementedError\n",
- "\n",
- " def call_mailer(self, data):\n",
- " raise NotImplementedError"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Then we need to implement this interface with a dummy object just to pass our current module as its dependency so we are able to test the controller calling for mailer"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [],
- "source": [
- "class DummyController(ControllerInterface):\n",
- " def __init__(self, mailer):\n",
- " self.mailer = mailer\n",
- " \n",
- " def call_mailer(self, data):\n",
- " self.mailer.send(data)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "After this we must test if calling the DummyController will invoke the mailer with the correct args and to do so we must define a mailer for now and we are able to use the patch object from the unittest.mock library to check if a function was called correctly"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {},
- "outputs": [],
- "source": [
- "class Mailer():\n",
- " def send(self, data):\n",
- " pass"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {},
- "outputs": [],
- "source": [
- "from unittest.mock import patch"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We are able to check if a function was called with certain arguments by using `assert_called_with`"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [],
- "source": [
- "@patch.object(Mailer, 'send')\n",
- "def test_controller(mock_send):\n",
- " controller = DummyController(Mailer())\n",
- " data = {}\n",
- " controller.call_mailer(data)\n",
- " mock_send.assert_called_with(data)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [],
- "source": [
- "test_controller()"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.7.7"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/testgranularity/integrationtesting.ipynb b/testgranularity/integrationtesting.ipynb
new file mode 100644
index 0000000..408025b
--- /dev/null
+++ b/testgranularity/integrationtesting.ipynb
@@ -0,0 +1,175 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Integration Testing\n",
+ "===================\n",
+ "\n",
+ "It is a step in the testing process that lies among unit tests and system tests. All the modules of the system, that ideally were tested in unit tests, are combined to guarantee that they work together properly. We can consider that it works as a preparation for System tests. Data is transferred between the modules and is tested thoroughly.\n",
+ "\n",
+ "Let's consider a scenario where a mailing system that records all emails sent is developed, and its modules are assigned to different developers. Using the image below as an example, each module could be due to a different programer to develop in order to increase velocity. The front API can be any kind of interface for the client to invoke like a website or a rest API, the controller is responsible for invoking the mailer service and recording the history using the Data Access Layer which is a layer for accessing some kind of storage which will be able to save the emails history in a structure somehow.\n",
+ "\n",
+ "![Diagram](../assets/integrationtesting_diagram.png)\n",
+ "\n",
+ "## Hands On\n",
+ "\n",
+ "- A Driver example with Python\n",
+ " \n",
+ "
\n",
+ ""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "First we implement a common interface which has a contract of how we are going to call the lower modules under construction"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "class ControllerInterface():\n",
+ " def __init__(self, mailer):\n",
+ " raise NotImplementedError\n",
+ "\n",
+ " def call_mailer(self, data):\n",
+ " raise NotImplementedError"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Then we need to implement this interface with a dummy object just to pass our current module as its dependency so we are able to test the controller calling for mailer"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "class DummyController(ControllerInterface):\n",
+ " def __init__(self, mailer):\n",
+ " self.mailer = mailer\n",
+ " \n",
+ " def call_mailer(self, data):\n",
+ " self.mailer.send(data)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "After this we must test if calling the DummyController will invoke the mailer with the correct args and to do so we must define a mailer for now and we are able to use the patch object from the unittest.mock library to check if a function was called correctly"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "class Mailer():\n",
+ " def send(self, data):\n",
+ " pass"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from unittest.mock import patch"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We are able to check if a function was called with certain arguments by using `assert_called_with`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "@patch.object(Mailer, 'send')\n",
+ "def test_controller(mock_send):\n",
+ " controller = DummyController(Mailer())\n",
+ " data = {}\n",
+ " controller.call_mailer(data)\n",
+ " mock_send.assert_called_with(data)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "test_controller()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Integration Strategies\n",
+ "\n",
+ "There are some methods to tackle the issue of testing this whole flow regarding the development of tests, one of them is the *Big Bang* [1] method which we code everything and then code the tests but this is usually a bad idea since it would cost more in time and it would be harder to trace errors since it is hard to isolate bugs, but it is also possible to test using an *Incremental Approach* [2] by developing the integration tests while working on the module, but to do so it is needed to input something similar to the output of the original module and the modules must agree beforehand their expected outputs and inputs, eg.: It is possible to test the Front API by faking the controller response and passing it as an input for the Front API.\n",
+ "\n",
+ "## Situational Examples\n",
+ "\n",
+ "Let's say that we are developing the controller but the Data Access Layer (DAL) and the Mailer Service are still under development, but we still need to test the controller somehow and to do so it is possible to use stubs to replace the DAL and the Mailer Service. Stubs are simple objects with pre-determined answers for certain executions durint the tests.\n",
+ "\n",
+ "Now we can assume that the Mailer Service and the DAL are under development but the controller is not ready yet, but we need to test the controller behavior on dealing with both modules. Using a Driver in this scenario may be the best option since the Driver is a provisional module that emulates the behavior of a module in a upper level and in this case it would emulate the Controller.\n",
+ "\n",
+ "## Techniques\n",
+ "\n",
+ "Depending on the language used on the project it is possible to have more or less flexibility on testing, for example, in Python there isn't a hard limitation for accessing private fields, so it is easy to access such fields and the language provides native support to do so, but on the other hand, JVM based languages such as Java, locks any kind of access to private fields during tests, but there are some frameworks that are able to tweak the generated bytecode during the compile in order to expose those fields only for testing. But in most languages it is possible to use some of the techniques detailed bellow.\n",
+ "\n",
+ "- Dummy objects with no funcionality that just needs to fill some space like filling parameters. In our sample mailer this could be done by implement a fake mailer service with the same interface as the original service but with no function and pre configured results.\n",
+ "- *Mocking* [3] is a technique that aims to create simulated version of objects related to your application in order to assert that the functions were called correctly or to simulate only certain functions of an implemented object. This could be used to mock the DAL access to a real database and return fake results only for testing purposes.\n",
+ "\n",
+ "## References\n",
+ "\n",
+ "1. Software Testing Dictionary. [Blog] Available at: [Accessed 10 August 2020].\n",
+ "2. What Is Incremental Testing: Detailed Explanation With Examples. [Blog] Available at: [Accessed 10 August 2020].\n",
+ "3. Osherove, Roy (2009). \"Interaction testing with mock objects et seq\". The art of unit testing. Manning. ISBN 978-1-933988-27-6.\n",
+ "\n",
+ "\n"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.5"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/testgranularity/integrationtesting.md b/testgranularity/integrationtesting.md
deleted file mode 100644
index 9ca1c9d..0000000
--- a/testgranularity/integrationtesting.md
+++ /dev/null
@@ -1,44 +0,0 @@
-Integration Testing
-===================
-
-It is a step in the testing process that lies among unit tests and system tests. All the modules of the system, that ideally were tested in unit tests, are combined to guarantee that they work together properly. We can consider that it works as a preparation for System tests. Data is transferred between the modules and is tested thoroughly.
-
-Let's consider a scenario where a mailing system that records all emails sent is developed, and its modules are assigned to different developers. Using the image below as an example, each module could be due to a different programer to develop in order to increase velocity. The front API can be any kind of interface for the client to invoke like a website or a rest API, the controller is responsible for invoking the mailer service and recording the history using the Data Access Layer which is a layer for accessing some kind of storage which will be able to save the emails history in a structure somehow.
-
-![Diagram](../assets/integrationtesting_diagram.png)
-
-## Integration Strategies
-
-There are some methods to tackle the issue of testing this whole flow regarding the development of tests, one of them is the *Big Bang* [1] method which we code everything and then code the tests but this is usually a bad idea since it would cost more in time and it would be harder to trace errors since it is hard to isolate bugs, but it is also possible to test using an *Incremental Approach* [2] by developing the integration tests while working on the module, but to do so it is needed to input something similar to the output of the original module and the modules must agree beforehand their expected outputs and inputs, eg.: It is possible to test the Front API by faking the controller response and passing it as an input for the Front API.
-
-## Situational Examples
-
-Let's say that we are developing the controller but the Data Access Layer (DAL) and the Mailer Service are still under development, but we still need to test the controller somehow and to do so it is possible to use stubs to replace the DAL and the Mailer Service. Stubs are simple objects with pre-determined answers for certain executions durint the tests.
-
-Now we can assume that the Mailer Service and the DAL are under development but the controller is not ready yet, but we need to test the controller behavior on dealing with both modules. Using a Driver in this scenario may be the best option since the Driver is a provisional module that emulates the behavior of a module in a upper level and in this case it would emulate the Controller.
-
-## Techniques
-
-Depending on the language used on the project it is possible to have more or less flexibility on testing, for example, in Python there isn't a hard limitation for accessing private fields, so it is easy to access such fields and the language provides native support to do so, but on the other hand, JVM based languages such as Java, locks any kind of access to private fields during tests, but there are some frameworks that are able to tweak the generated bytecode during the compile in order to expose those fields only for testing. But in most languages it is possible to use some of the techniques detailed bellow.
-
-- Dummy objects with no funcionality that just needs to fill some space like filling parameters. In our sample mailer this could be done by implement a fake mailer service with the same interface as the original service but with no function and pre configured results.
-- *Mocking* [3] is a technique that aims to create simulated version of objects related to your application in order to assert that the functions were called correctly or to simulate only certain functions of an implemented object. This could be used to mock the DAL access to a real database and return fake results only for testing purposes.
-
-## Hands On
-
-- Mocking with Python
-
-
-
-
-- A Driver example with Python
-
-
-
-
-
-## References
-
-1. Software Testing Dictionary. [Blog] Available at: [Accessed 10 August 2020].
-2. What Is Incremental Testing: Detailed Explanation With Examples. [Blog] Available at: [Accessed 10 August 2020].
-3. Osherove, Roy (2009). "Interaction testing with mock objects et seq". The art of unit testing. Manning. ISBN 978-1-933988-27-6.
diff --git a/testgranularity/mocking.ipynb b/testgranularity/mocking.ipynb
deleted file mode 100644
index 81e49bf..0000000
--- a/testgranularity/mocking.ipynb
+++ /dev/null
@@ -1,168 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Mocking with Python"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## In this notebook, we have a test example that, by the use of the `Mock` library, gives us more control on testing\n",
- "\n",
- "### Pro tips:\n",
- "- To run this notebook interactively, select the rocket in the above menu and select `binder`"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 76,
- "metadata": {},
- "outputs": [],
- "source": [
- "from datetime import datetime"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 77,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Here we implement a function to check if the current day is a weekday\n",
- "\n",
- "def is_weekday():\n",
- " today = datetime.today()\n",
- " # Python's datetime library treats Monday as 0 and Sunday as 6\n",
- " return (0 <= today.weekday() < 5)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 78,
- "metadata": {},
- "outputs": [
- {
- "ename": "AssertionError",
- "evalue": "",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mAssertionError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# Test if today is a weekday\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0;32massert\u001b[0m \u001b[0mis_weekday\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[0;31mAssertionError\u001b[0m: "
- ]
- }
- ],
- "source": [
- "# Test if today is a weekday\n",
- "\n",
- "# In this cell, you should edit it depending on the day you're seeing this exercise in order to make the test pass. That's not an expectaded behavior in software testing! In next cells, we use mocks to prevent it!\n",
- "\n",
- "# assert is_weekday() # from monday to friday\n",
- "# assert not is_weekday() # for saturday and sunday\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "If you think for a while, we have a test case which the assertion result may vary depending on which day of the week the test is actually run! If you run it from Monday to Friday, it shall pass, otherwise, it won't.\n",
- "\n",
- "To have more control on what the object generate, we can use Mock to modify the `return` from the function. Let's do it!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 86,
- "metadata": {},
- "outputs": [],
- "source": [
- "import datetime\n",
- "from unittest.mock import Mock"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 87,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Save a couple of test days to use as mocking! Go ahead and change it as you desire!\n",
- "tuesday = datetime.datetime(year=2020, month=7, day=7)\n",
- "saturday = datetime.datetime(year=2020, month=7, day=11)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 88,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Mock datetime to control today's date, as we want to return or custom days\n",
- "datetime = Mock()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 89,
- "metadata": {},
- "outputs": [],
- "source": [
- "def is_weekday():\n",
- " today = datetime.datetime.today()\n",
- " # Python's datetime library treats Monday as 0 and Sunday as 6\n",
- " return (0 <= today.weekday() < 5)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 90,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Mock .today() to return Tuesday\n",
- "datetime.datetime.today.return_value = tuesday\n",
- "\n",
- "# Test Tuesday is a weekday\n",
- "assert is_weekday()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 91,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Mock .today() to return Saturday\n",
- "datetime.datetime.today.return_value = saturday\n",
- "# Test Saturday is not a weekday\n",
- "assert not is_weekday()"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.7.7"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}