Question: Complete the unit tests provided in the classesTestTwoDPointandTestQuadrilateral. Write unit test classesTestRectangleandTestSquare. In these classes, you must write unit test methods for Rectangle'scenter()andarea()methods, and Square'ssnap()method.

  1. Complete the unit tests provided in the classesTestTwoDPointandTestQuadrilateral.
  2. Write unit test classesTestRectangleandTestSquare. In these classes, you must write unit test methods for Rectangle'scenter()andarea()methods, and Square'ssnap()method.

test_quadrilateral.py

from unittest import TestCase

class TestQuadrilateral(TestCase):

def test_side_lengths(self):

self.fail()# TODO

def test_smallest_x(self):

self.fail()# TODO

test_twoDPoint.py

from unittest import TestCase

class TestTwoDPoint(TestCase):

def test_from_coordinates(self):

self.fail()# TODO

two_d_point.py

from typing import List

import math

class TwoDPoint:

def __init__(self, x, y) -> None:

self.__x = x

self.__y = y

@property

def x(self):

return self.__x

@property

def y(self):

return self.__y

def __eq__(self, other: object) -> bool:

if self.x == other.x and self.y == other.y:

return True

return False

def __ne__(self, other: object) -> bool:

return not self.__eq__(other)

def __str__(self) -> str:

return '(%g, %g)' % (self.__x, self.__y)

def __add__(self, other):

return TwoDPoint(self.x + other.x, self.y + other.y)

def __sub__(self, other):

return TwoDPoint(self.x - other.x, self.y - other.y)

@staticmethod

def from_coordinates(coordinates: List[float]):

if len(coordinates) % 2 != 0:

raise Exception("Odd number of floats given to build a list of 2-d points")

points = []

it = iter(coordinates)

for x in it:

points.append(TwoDPoint(x, next(it)))

return points

def distance(self, other) -> float:

"""

This method calculates the distance between two points.

"""

return math.sqrt((self.x-other.x)*(self.x-other.x) + (self.y-other.y)*(self.y-other.y))

quadrilateral.py

from two_d_point import TwoDPoint

class Quadrilateral:

def __init__(self, *floats):

points = TwoDPoint.from_coordinates(list(floats))

self.__vertices = tuple(points[0:4])

@property

def vertices(self):

return self.__vertices

def side_lengths(self):

"""Returns a tuple of four floats, each denoting the length of a side of this quadrilateral. The value must be

ordered clockwise, starting from the top left corner."""

# Finding the center of the quadrlateral.

center = self.vertices[0] + self.vertices[1] + self.vertices[2] + self.vertices[3]

center = TwoDPoint(center.x/4, center.y/4)

# Stores the points of the quadrilateral in clockwise order,

# starting from top-left.

point_in_order = [None, None, None, None]

# Adding the points in order.

for i in range(0, len(self.vertices)):

if self.vertices[i].x <= center.x and self.vertices[i].y >= center.y:

point_in_order[0] = self.vertices[i]

elif self.vertices[i].x >= center.x and self.vertices[i].y >= center.y:

point_in_order[1] = self.vertices[i]

elif self.vertices[i].x >= center.x and self.vertices[i].y <= center.y:

point_in_order[2] = self.vertices[i]

elif self.vertices[i].x <= center.x and self.vertices[i].y <= center.y:

point_in_order[3] = self.vertices[i]

# Calculating the distances between adjacent points.

distances = []

for i in range(0, len(point_in_order)):

distances.append(point_in_order[i].distance(point_in_order[(i+1)%4]))

# Return the distance as tuple.

return tuple(distances)

def smallest_x(self):

"""Returns the x-coordinate of the vertex with the smallest x-value of the four vertices of this

quadrilateral."""

# Stores the smallest x, initialized as the first point.

smallest_x = self.vertices[0].x

# Iterating over the points and calculating the smallest x

for point in self.vertices:

if point.x < smallest_x:

smallest_x = point.x

return smallest_x

rectangle.py

from quadrilateral import Quadrilateral

from two_d_point import TwoDPoint

class Rectangle(Quadrilateral):

def __init__(self, *floats):

super().__init__(*floats)

if not self.__is_member():

raise TypeError("A rectangle cannot be formed by the given coordinates.")

def __is_member(self):

"""Returns True if the given coordinates form a valid rectangle, and False otherwise."""

# Each x and y coordinate in a rectange should occur twice since the rectangle

# is alligned with the axes. We use this to determine if it's a rectangle.

# Stores the count of x coordinates.

x_coordinates = {}

# Stores the count of y coordinates.

y_coordinates = {}

# Counting the occurance of each x and y coordinate.

for point in self.vertices:

if point.x in x_coordinates:

x_coordinates[point.x] += 1

else:

x_coordinates[point.x] = 1

if point.y in y_coordinates:

y_coordinates[point.y] += 1

else:

y_coordinates[point.y] = 1

# Checking if each coordinate occurs two times.

for x in x_coordinates:

if x_coordinates[x] != 2:

return False

for y in y_coordinates:

if y_coordinates[y] != 2:

return False

return True

def center(self):

center = self.vertices[0] + self.vertices[1] + self.vertices[2] + self.vertices[3]

return TwoDPoint(center.x/4, center.y/4)

def area(self):

"""Returns the area of this rectangle. The implementation invokes the side_lengths() method from the superclass,

and computes the product of this rectangle's length and width."""

side_lengths = self.side_lengths()

return side_lengths[0]*side_lengths[1]

square.py

from two_d_point import TwoDPoint

from rectangle import Rectangle

from quadrilateral import Quadrilateral

class Square(Rectangle):

def __init__(self, *floats):

super().__init__(*floats)

if not self.__is_member():

raise TypeError("A square cannot be formed by the given coordinates.")

def __is_member(self):

# The adjacent sides of the square should be equal.

side_lengths = self.side_lengths()

if side_lengths[0] != side_lengths[1]:

return False

return True

def snap(self):

"""Snaps the sides of the square such that each corner (x,y) is modified to be a corner (x',y') where x' is the

integer value closest to x and y' is the integer value closest to y. This, of course, may change the shape to a

general quadrilateral, hence the return type. The only exception is when the square is positioned in a way where

this approximation will lead it to vanish into a single point. In that case, a call to snap() will not modify

this square in any way."""

# Stores the snapped points.

snapped_points = []

for point in self.vertices:

snapped_points.append(TwoDPoint(round(point.x), round(point.y)))

# Checking that all snapped points are not equal,

# in which case the square itself is returned.

if snapped_points[0] == snapped_points[1] and snapped_points[0] == snapped_points[2] and snapped_points[0] == snapped_points[3]:

return self

# Returning the quadrilateral with snapped points.

return Quadrilateral(snapped_points[0].x, snapped_points[0].y, snapped_points[1].x, snapped_points[1].y, snapped_points[2].x, snapped_points[2].y, snapped_points[3].x, snapped_points[3].y)

Step by Step Solution

There are 3 Steps involved in it

1 Expert Approved Answer
Step: 1 Unlock blur-text-image
Question Has Been Solved by an Expert!

Get step-by-step solutions from verified subject matter experts

Step: 2 Unlock
Step: 3 Unlock

Students Have Also Explored These Related Programming Questions!