Ssd Unit 6

8 minute read

Published:

Learning Outcomes Achieved

  1. Critically analyse development problems and determine appropriate methodologies, tools and techniques to solve them

Unit Testing Codio Activity

Question 1

  • What happens when the code is run? The code fails to execute due to an IndentationError.
  • Can you modify this code for a more favourable outcome/What amendments have you made to the code? The code can be indented manually using Tab characters, to resolve the error and ensure that Python can parse the code. Despite making this change, running the file will not cause anything to happen because the function isn’t called in the file- a test can be added to verify that the function is working as expected.

The final code is presented below:

# CODE SOURCE: SOFTWARE ARCHITECTURE WITH PYTHON 

def factorial(n):
    """ Return factorial of n """
    if n == 0:
        return 1
    else:
        return n*factorial(n-1)

print "Test that factorial(3) is 6. Test passed? {result}".format(result=factorial(3) == 6)

Question 2- Pylint

After running pylint on pylintTest.py, 4 types of errors were found:

  • Indentation errors
  • Improper naming
  • Lack of proper whitespace
  • Variable redefinition
  • Missing docstring

The corrected code is provided below. This code was given a perfect score by pylint:

pylint_test_fixed.py

"""
This module contains code which can encode or decode some given text.
"""
# SOURCE OF CODE: https://docs.pylint.org/en/1.6.0/tutorial.html

import string

SHIFT = 3
CHOICE = raw_input("would you like to encode or decode?")
WORD = (raw_input("Please enter text"))
LETTERS = string.ascii_letters + string.punctuation + string.digits
ENCODED = ''
if CHOICE == "encode":
    for letter in WORD:
        if letter == ' ':
            ENCODED = ENCODED + ' '
        else:
            x = LETTERS.index(letter) + SHIFT
            ENCODED = ENCODED + LETTERS[x]
if CHOICE == "decode":
    for letter in WORD:
        if letter == ' ':
            ENCODED = ENCODED + ' '
        else:
            x = LETTERS.index(letter) - SHIFT
            ENCODED = ENCODED + LETTERS[x]

print ENCODED

Question 3

  • Review the errors returned. In what way does this error message differ from the error message returned by pylint? The output of flake8 provides information around spacing and indentation only, whereas pylint provided information regarding best practices for variable naming, file naming, and module documentation. Pylint also provides a score on how adherent the module is to best practices, and how the file has improved since the last check.

  • Can you correct each of the errors returned by flake8/What amendments have you made to the code? Deleted line numbers, fixed indentation, fixed missing/unused imports, corrected invalid variable references, used autopep8 to correct any uncaught issues, verified the file conforms to standards by running flake8 and verifying that no issues were reported.

metricTest.py


"""
Module metrictest.py

Metric example - Module which is used as a testbed for static checkers.
This is a mix of different functions and classes doing different things.

"""

import random


def fn(x, y):
    """ A function which performs a sum """
    return x + y


def find_optimal_route_to_my_office_from_home(start_time,
                                              expected_time,
                                              favorite_route='SBS1K',
                                              favorite_option='bus'):

    # If I am very late, always drive.
    d = (expected_time - start_time).total_seconds() / 60.0

    if d <= 30:
        return 'car'

    # If d>30 but <45, first drive then take metro
    if d > 30 and d < 45:
        return ('car', 'metro')

    # If d>45 there are a combination of options
    if d > 45:
        if d < 60:
            # First volvo,then connecting bus
            return ('bus:335E', 'bus:connector')
        elif d > 80:
            # Might as well go by normal bus
            return random.choice(('bus:330',
                                  'bus:331',
                                  ':'.join((favorite_option, favorite_route))))
        elif d > 90:
            # Relax and choose favorite route
            return ':'.join((favorite_option,
                             favorite_route))


class C(object):
    """ A class which does almost nothing """

    def __init__(self, x, y):
        self.x = x
        self.y = y

    def f(self):
        pass

    def g(self, x, y):
        if self.x > x:
            return self.x+self.y
        elif x > self.x:
            return x + self.y


class D(C):
    """ D class """

    def __init__(self, x):
        self.x = x

    def f(self, x, y):
        if x > y:
            return x-y
        else:
            return x+y

    def g(self, y):
        if self.x > y:
            return self.x+y
        else:
            return y-self.x


def myfunc(a, b):
    if a > b:
        return b
    else:
        return a

Question 4

  • Run mccabe on sums.py. What is the result?
("4:0: 'test_sum'", 1)
('If 7', 2)
  • Run mccabe on sums2.py. What is the result?
("7:0: 'test_sum_tuple'", 1)
("4:0: 'test_sum'", 1)
('If 10', 2)
  • What are the contributors to the cyclomatic complexity in each piece of code? In sums.py, the main contributors to cyclomatic complexity are the if/else branch, and the iteration through the list given as a parameter to sum. In sums2.py, the main contributors to cyclomatic complexity are the two list arguments given as parameters to sum, and the 2 resulting if/else statements which assert that the output is correct. Note that the if/else statements are implicit and part of the assert.

Reflection

From these questions, I improved my understanding of code quality and achieved learning outcome 2 because code quality can be seen as a development (as well as a security) problem, however, linters can help manage it. Although the suggested tools are useful, manual effort is required to resolve any issues detected by a linter. I have personally worked with autopep8, and find it useful because it automatically formats code to fit Python’s best practice. For the implementation assignment, I will recommend a practice of automatically formatting code via autopep8 before creating a pull request. In addition, I will also attempt to integrate a linter with CircleCI, ensuring that any non-compliant code will not be deployed.

Design Document Feedback

Although the team received positive feedback from the professor regarding the assignment, the feedback given gave me something to consider: enforcing logical consistency in writing. A key criticism was that many suggested technologies lacked adequate/clear justification. I feel that a challenge in doing this, was providing as much detail as possible within the wordcount. The first complete iteration of the document was approximately 1600 words, and the majority of time spent before submission, was on reducing the wordcount. My idea for reducing the wordcount at that time was to use references to provide the necessary justification while keeping the wordcount low. After rereading the assignment in light of the given feedback, I realize that this approach makes arguments much harder to understand, and would still cause a reader to ask what the justification for a specific argument is. I think that the real problem was that certain details were included that were too superfluous because they were too detailed for what is needed for the design at this stage. As an example, there was a fairly detailed discussion regarding database speeds, along with additional detail on which OOP principles need to be applied. These sections could have been skipped in favor of writing clearer justifications. In future, I will ensure that I check arguments for unnecessary details, which I think would best be achieved by asking myself the question “If this detail is removed, can my overall point still be shown to be sound?”

Overall, this exercise helped me achieve learning outcomes 1 and 2 because I was able to critically analyze design requirements, find threats, and manage them in a safe way. Additionally, I determined how the intended development process could lead to challenges (e.g. deployment authentication), and suggested practices to eliminate these challenges.

Additionally, working in a team helped me achieve learning outcome 4 because I was able to learn more about managing team productivity digitally. After some reflection, I attribute a substantial part of this success to the usage of diverse communication channels. It was much easier to find information when platforms were used for specific purposes (for example, Discord was for quick questions and voice chat, Slack was for extended discussion and meeting recaps, while Trello was used to manage milestones and deliverables). Later in development, Victor introduced Miro for collaborative diagramming. Having these clear boundaries for each application improved my productivity, and digital recordkeeping ensured that nobody forgot any tasks or requirements. This is something I will apply to my working life- one area I would like to test out, is using a calendar application to keep track of meetings and deadlines.