Subscribe To Our Newsletter
You will receive our latest post and tutorial.
Thank you for subscribing!

required
required


Hasura – Subscription

 

March 17, 2020

Hasura – Metadata

 

March 17, 2020

Python – Testing

Testing in programming is a best practice that all developers should undertand and utilize. A testing unit should focus on one tiny bit of functionality and prove it correct. Each test unit must be fully independent. Each test must be able to run alone, and also within the test suite, regardless of the order that they are called. The implication of this rule is that each test must be loaded with a fresh dataset and may have to do some cleanup afterwards. This is usually handled by setUp() and tearDown() methods.

Example

Here is tests.py

import unittest
import functions

class TestClass(unittest.TestCase):
    def test_multiplication(self):
        self.assertEqual(functions.multiply(3,3), 9, "should be 9")
    
if __name__ == '__main__':
    unittest.main()

Here is functions.py

def add(num1, num2):
    return num1 + num2;

def multiply(num1, num2):
    return num1 * num2;

setUp and testDown functions

Tests can be numerous, and their set-up can be repetitive. Luckily, we can factor out set-up code by implementing a method called setUp(), which the testing framework will automatically call for every single test we run. Note that the order in which the various tests will be run is determined by sorting the test method names with respect to the built-in ordering for strings. If the setUp() method raises an exception while the test is running, the framework will consider the test to have suffered an error, and the test method will not be executed. We can provide a tearDown() method that tidies up after the test method has been run. If setUp() succeeded, tearDown() will be run whether the test method succeeded or not.

class TestClass(unittest.TestCase):
    def setUp(self):
        print("set up")

    def test_multiplication(self):
        self.assertEqual(functions.multiply(3,3), 9, "should be 9")
    
    def tearDown(self):
        print("tear down")

if __name__ == '__main__':
    unittest.main()

 Test Suite

It is recommended that we use TestCase implementations to group tests together according to the features we test.

import unittest
import functions
from tests import TestClass

def suite():
    suite = unittest.TestSuite()
    suite.addTest(TestClass('test_multiplication'))
    return suite

if __name__ == '__main__':
    runner = unittest.TextTestRunner()
    runner.run(suite())
class TestClass(unittest.TestCase):
    def setUp(self):
        print("set up")

    def test_multiplication(self):
        self.assertEqual(functions.multiply(3,3), 9, "should be 9")

    def tearDown(self):
        print("tear down")

How to skip tests

Skipping a test is simply a matter of using the skip() decorator or one of its conditional variants, calling TestCase.skipTest() within a setUp() or test method, or raising SkipTest directly.

class TestClass(unittest.TestCase):
    def setUp(self):
        print("set up")

    @unittest.skip("demonstrating skipping")
    def test_multiplication(self):
        self.assertEqual(functions.multiply(3,3), 9, "should be 9")

    def tearDown(self):
        print("tear down")

if __name__ == '__main__':
    unittest.main()

Source code on Github

 

Testing with Pytest

 

March 8, 2020

Python – User Input

Python allows for user input. That means we are able to ask the user for input either to interact with users and get data to provide some sort of result. Most programs today use a dialog box for that but for console we are using input.

input() function

The input from the user is read as a string and in most cases is assigned to a variable. After entering the value from the keyboard, you have to press the “Enter/Return” button. Then the input() function reads the value entered by the user.

Syntax

variable = input(message)

The message string is displayed on the console and the control is given to the user to enter the value. You should print some useful information to guide the user to enter the expected value.

Example

name = input("What is your name:")
print("Hello " + name+"! Welcome to my Tutorial.")

Input numeric values

favoriteNumber = int(input("What is your favorite number? "))
print("Your favorite number is {}".format(favoriteNumber))

If you put in a non numeric value, you will get this error which means that you input an invalid value for int

ValueError: invalid literal for int() with base 10

Source code on Github

March 8, 2020

Python – OOP

What is OOP?

Object-oriented programming has some advantages over other design patterns. Development is faster and cheaper, with better software maintainability. This, in turn, leads to higher-quality software, which is also extensible with new methods and attributes. The learning curve is, however, steeper. The concept may be too complex for beginners. Computationally, OOP software is slower, and uses more memory since more lines of code have to be written.

Python is a multi-paradigm programming language. It supports different programming approaches including OOP.

An object has two characteristics:

  • attributes
  • behavior

OOP works with classes and objects. A class is a blueprint for the object. An object (instance) is an instantiation of a class. When class is defined, only the description for the object is defined. Therefore, no memory or storage is allocated.

class User():
    name = str
    age = int
    admin_type = "ADMIN"
    user_type = "USER"

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def get_name(self):
        return self.name

Inheritance

Inheritance is a way of creating a new class for using details of an existing class without modifying it. The newly formed class is a derived class (or child class). Similarly, the existing class is a base class (or parent class).

class User():
    name = str
    age = int
    admin_type = "ADMIN"
    user_type = "USER"

    def __init__(self, name, age):
        self.name = name
        self.age = age

class Manager(user.User):

    def __init__(self, name, age):
        # call super() function
        super().__init__(name, age)
        print("Manager is ready")

    #inheritance
    man = Manager("Laulau",23)
    print(man.get_name())

# output
Laulau

Encapsulation

Using OOP in Python, we can restrict access to methods and variables. This prevents data from direct modification which is called encapsulation. In Python, we denote private attributes using underscore as the prefix i.e single _ or double __.

class Manager(user.User):

    def __init__(self, name, age, active):
        # call super() function
        super().__init__(name, age)
        self._active = True
        print("Manager is ready")

# OOP - inheritance, encapsulation
man = Manager("Laulau",23, False)
print(man.is_active()

# output
False

Polymorphism

Polymorphism is an ability (in OOP) to use a common interface for multiple forms (data types).

Suppose, we need to color a shape, there are multiple shape options (rectangle, square, circle). However we could use the same method to color any shape. This concept is called Polymorphism.

class Manager(user.User):

    def __init__(self, name, age, active):
        # call super() function
        super().__init__(name, age)
        self._active = True
        print("Manager is ready")

    def is_active(self):
        return self._active

class CTO(user.User):

    def __init__(self, name, age, active):
        # call super() function
        super().__init__(name, age)
        self._active = True
        print("Manager is ready")

    def is_active(self):
        return self._active

def print_user(man):
    print(man.__dict__)
    print(man.is_active())

man = Manager("Laulau",23, False)

cto = CTO("Laulau",23, False)

print_user(man)
print_user(cto)

# output
{'name': 'Laulau', 'age': 23, '_active': True}
True
{'name': 'Laulau', 'age': 23, '_active': True}
True

 

Key take aways

  • Object-Oriented Programming makes the program easy to understand as well as efficient.
  • Since the class is sharable, the code can be reused.
  • Data is safe and secure with data abstraction.
  • Polymorphism allows the same interface for different objects, so programmers can write efficient code.

Source code on Github

March 8, 2020