Sprint Challenge: Software Engineering
Sprint Challenge Overview
This sprint challenge will assess your understanding of the concepts covered throughout this sprint on Software Engineering. You'll demonstrate your ability to create Python modules, apply object-oriented programming principles, write clean code following PEP 8 standards, and implement comprehensive testing for your applications.
Challenge Instructions
Software Engineering - the Acme Way
Introduction
In this sprint challenge you will write code to demonstrate competency in writing your own Python modules, object-oriented programming, code style, and testing. You may use any tools and references you wish, but your final code should reflect your own work and be saved in .py
files (not notebooks).
For all your code, you may only import/use the following:
pytest
(from the standard library)random
(from the standard library)
Part 1 - Keeping it Classy
name
(string with no default)price
(integer with default value 10)weight
(integer with default value 20)flammability
(float with default value 0.5)identifier
(integer – a randomly generated number from a uniform distribution ranging from 1000000 to 9999999.) Both ends of this range are inclusive, meaning that it should be possible for the random generation to result in exactly 1000000 or 9999999 (although the probability of either of these being chosen is very small)
__init__
constructor
acme.py
, and you can test your code in a Python REPL as
>>> from acme import Product
>>> prod = Product('A Cool Toy')
>>> prod.name
'A Cool Toy'
>>> prod.price
10
>>> prod.weight
20
>>> prod.flammability
0.5
>>> prod.identifier
2812086 # your value will vary
Part 2 - Objects that Go!
stealability(self)
- calculates the price divided by the weight, and then returns a message:- if the ratio is less than 0.5 return "Not so stealable..."
- if it is greater or equal to 0.5 but less than 1.0 return "Kinda stealable."
- otherwise return "Very stealable!"
explode(self)
- calculates the flammability times the weight, and then returns a message:- if the product (result of the multiplication operation) is less than 10 return "...fizzle."
- if it is greater or equal to 10 but less than 50 return "...boom!"
- and otherwise return "...BABOOM!!"
>>> from acme import Product
>>> prod = Product('A Cool Toy')
>>> prod.stealability()
'Kinda stealable.'
>>> prod.explode()
'...boom!'
Part 3 - A Proper Inheritance
Product
named BoxingGlove
and does the following:
- Change the default
weight
to 10 (but leave other defaults unchanged) - Override the
explode
method to always return "...it's a glove." - Add a
punch
method that returns:- "That tickles." if the weight is below 5
- "Hey that hurt!" if the weight is greater or equal to 5 but less than 15
- "OUCH!" otherwise
>>> from acme import BoxingGlove
>>> glove = BoxingGlove('Punchy the Third')
>>> glove.price
10
>>> glove.weight
10
>>> glove.punch()
'Hey that hurt!'
>>> glove.explode()
"...it's a glove."
Part 4 - Class Report
Product
and BoxingGlove
objects, let's use these classes to write an acme_report.py
module (Python file) to generate random products and print a summary of them. For the purposes of these functions we will only use the Product
class.
generate_products(num_products=30)
should randomly generate a given number of products (default 30), and return them as a listinventory_report(product_list)
takes a list of products, and returns a tuple that holds some basic statistics about the list of products
name
should consist of a random adjective from the list:['Awesome', 'Shiny', 'Impressive', 'Portable', 'Improved']
followed by a space and then a random noun from the list:['Anvil', 'Catapult' 'Disguise' 'Mousetrap', '???']
, e.g.'Awesome Anvil'
and'Portable Catapult'
are both potential names that could be generatedprice
andweight
should both be random integers from 5 to 100 (inclusive)flammability
should be a float ranging from 0.0 to 2.5 (inclusive)
random
module from the Python standard library to assist you in generating the above values. Since the random module is included in the Python standard library, you shouldn't need to install anything in order to use it, you can import it at the top of your file without having to do anything else.
Product
class from acme.py
. You will want to generate a set of random values and then pass those values as parameters to the Product()
class constructor function. This function will return back to you a new product object that you can append to a list. You will want to do this many times over, so a for loop might help you repeat this process as many times as is required.generate_products()
function to override the default value, so don't forget to include the default parameter.inventory_report()
, you should calculate the following values in regards to the product list generated by your generate_products()
function:- Number of unique product names in the product list
- Average (mean) price
- Average (mean) weight
- Average (mean) flammability
Once you have calculated these values, combine the four numbers into a tuple and return the tuple from the function.
acme_report.py
:import random
from acme import Product
# Useful to use with random.sample or random.choice to generate names
ADJECTIVES = ['Awesome', 'Shiny', 'Impressive', 'Portable', 'Improved']
NOUNS = ['Anvil', 'Catapult', 'Disguise', 'Mousetrap', '???']
def generate_products(num_products=30):
products = []
# TODO - your code! Generate and add random products to the list
return products
def inventory_report(products):
pass # TODO - your code! Use the products list to calculate the report.
if __name__ == '__main__':
print(inventory_report(generate_products()))
$ python acme_report.py
(19, 56.8, 54.166666666666664, 1.258097155966675)
>>> s = set()
>>> s.add(1)
>>> s.add(2)
>>> s
{1, 2}
>>> s.add(3)
>>> s.add(1)
>>> s
{1, 2, 3}
>>> len(s)
3
>>> my_list = [1,3,4,2,4,3,2,3]
>>> my_set = set(my_list)
>>> my_set
{1, 2, 3, 4}
Part 5 - Measure twice, Test once
acme_test.py
starting from the following code:import pytest
from acme import Product
from acme_report import generate_products, ADJECTIVES, NOUNS
def test_default_product_price():
'''Test default product price being 10.'''
prod = Product('Test Product')
assert prod.price == 10
- Add at least three more test functions to
acme_test.py
to test theProduct
class:- Test the product's default attributes (see the example code)
- Test the
stealability()
andexplode()
methods to ensure that they return the correct values - Test the default
generate_products()
function to ensure that it returns a list with 30 items in it
Part 6 - Style it Up
Part 7 - Turn it in!
acme.py
(holds yourProduct
andBoxingGlove
classes)acme_report.py
(holds yourgenerate_products()
andinventory_report()
functions)acme_test.py
(holds your –minimum of two– unit tests for theProduct
class)
Challenge Expectations
The Sprint Challenge is designed to test your mastery of the following key concepts:
- Python Modules and Packages: Creating well-structured Python files that can be imported and used
- Object-Oriented Programming: Implementing classes with proper constructors, methods, and inheritance
- Code Style and Standards: Following PEP 8 guidelines for clean, readable Python code
- Testing: Writing comprehensive unit tests to verify code functionality
- Random Data Generation: Using Python's random module to create realistic test data
What to Expect
In this sprint challenge, you'll apply everything you've learned about software engineering to build a complete Python application for Acme Corporation. This challenge will test your ability to:
- Design and implement Python classes with appropriate attributes and methods
- Apply inheritance to create specialized subclasses
- Create modules with functions that generate and analyze data
- Write comprehensive unit tests that verify your code works correctly
- Follow Python style guidelines and best practices
- Work with the random module to generate realistic test data
- Structure your code in a professional, maintainable way
Remember to demonstrate your understanding of the concepts from all four modules in this sprint!