Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 4 additions & 94 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,96 +1,6 @@
# Currency converter
Bret Runestad
currency conversion assignment

## Description
The convert function takes a list of rates, a starting value, and two strings: a 'from' string and a 'two' string. The list of rates must take the form of a list of tuples. Each tuple should take the form ('USD', 'EUR', 0.74), where the first two indexes are 3-letter codes for different currencies, and the 3rd index is the conversion rate from the first code to the second. The 'from' and 'to' strings must be 3-letter codes that correspond to existing pairs within the list of rates, although the order of the pair may be reversed. When run, the convert function will take the starting value, and convert that amount from the 'from' currency to the 'to' currency. It is as fun as it sounds.

Create a set of functions to convert currency from one denomination to another.

## Objectives

### Learning Objectives

After completing this assignment, you should understand:

* Test-driven development

### Performance Objectives

After completing this assignment, you should be able to:

* Raise exceptions
* Write detailed tests
* Break down programming problems into smaller ones

## Details

### Deliverables

* A Git repo called currency-converter containing at least:
* `README.md` file explaining how to run your project
* a `currency` module
* a `test_currency` set of tests

### Requirements

* Passing unit tests
* No PEP8 or Pyflakes warnings or errors
* No functions longer than 7 lines of code
* 100% test coverage

## Normal Mode

Use test-driven development to design a function called `convert`. Below is a list of all the things it should do. In order to complete this exercise, follow these directions:

* For each requirement, write a test first, and then make the test pass, do not pass Go, do not collect $200.
* Every time you finish a requirement, commit your code with a message describing the requirement.
* Go through the requirements one-by-one. Do not skip around.

### Steps:

* Create a function called `convert` that takes a list called `rates`, a number called `value`, a string called `from`, and a string called `to`. Make sure than when you call `convert` with `from` and `to` being equal, the return value is the same as `value`.

* `rates` list should be a list of tuples, with each tuple containing a currency code you can convert from, a currency code you can convert to, and a rate.

```py
[("USD", "EUR", 0.74)]
```

This means that each dollar is worth 0.74 euros.

`value` is the amount of currency, `from` is the current currency code, and `to` is the currency code you wish to convert to.

Given the above rates, make sure that converting 1 dollar into euros returns the following value: `0.74`.

* Next, test that you can convert currency with a `value` that is not 1.
* Next, test that converting 1 euro into dollars returns `1.35` (or an approximation).
* Create a new list of rates with two or more tuples. Make sure you can convert both ways with each rate. For example, with these rates:

```py
[("USD", "EUR", 0.74), ("EUR", "JPY", 145.949)]
```

Make sure you can convert from USD to EUR, EUR to USD, EUR to JPY, and JPY to EUR.

## Hard Mode

In addition to the requirements from **Normal Mode**:

* Make sure that if you try to make a conversion you do not know about, a `ValueError` is raised with an appropriate message.

* Test that you can convert between any two rates that you have the ability to, even if you do not have a direct conversion rate for them. For example, with the rates:

```py
[("USD", "EUR", 0.74), ("EUR", "JPY", 145.949)]
```

Make sure you can convert from USD to JPY.

This will probably require [Dijkstra's algorithm](http://rosettacode.org/wiki/Dijkstra%27s_algorithm).


## Additional Resources

* [Currency charts](http://www.xe.com/currencycharts/) if you want accurate values.
* The [pytest](http://pytest.org/latest/) testing framework.
* [An Introduction to Test Driven Development](https://www.codeenigma.com/community/blog/introduction-test-driven-development).
* [Test-Driven Development](https://en.wikibooks.org/wiki/Introduction_to_Software_Engineering/Testing/Test-driven_Development) on Wikibooks.
* [Test-Driven Development by Example](http://www.amazon.com/Test-Driven-Development-By-Example/dp/0321146530), the canonical book on this stuff.
The exception_check program is a small program whose sole purpose is to catch the IndexError that arises when the 'from' and 'to' strings do not match with a corresponding tuple.
29 changes: 29 additions & 0 deletions currency.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
def convert(rates, value, from_string, to_string):
"""Takes a list of rates, an amount of currency(value), a from_string, and
a to_string. It cross references the 'from' and 'to' strings to find the
applicable currency exchange rate. It then multiplies the value by that
rate, rounded to 2 decimal places."""
tuple_list = (
[x for x in rates if x[0] == from_string and x[1] == to_string])
if tuple_list:
return round(tuple_list[0][2] * value, 2)
else:
tuple_list2 = (
[x for x in rates if x[1] == from_string and x[0] == to_string])
return round((1/tuple_list2[0][2]) * value, 2)


def exception_check(rates, value, from_string, to_string):
"""Runs the convert program, but provides an error message for
unrecognized 'from' or 'to' strings"""
try:
return convert(rates, value, from_string, to_string)
except IndexError:
print(
"Sorry, at least one of the currency codes is not in my database")
return ("Error message")


if __name__ == "__main__":

rates = [("USD", "EUR", 0.74)]
62 changes: 62 additions & 0 deletions test_currency.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
from currency import*


def test_convert_value_check():
assert convert(rates=[('USD', 'USD', 1)],
value=5,
from_string='USD',
to_string='USD') == 5


def test_convert_dollar_to_euro():
rates = [('USD', 'EUR', .74), ('USD', 'JPY', 145.949)]
assert convert(rates,
value=1,
from_string='USD',
to_string='EUR') == 0.74


def test_convert_different_values():
rates = [('USD', 'EUR', .74), ('USD', 'JPY', 145.949)]
assert convert(rates, value=5,
from_string='USD', to_string='EUR') == 3.7
assert convert(rates, value=.2,
from_string='USD', to_string='EUR') == 0.15
assert convert(rates, value=0,
from_string='USD', to_string='EUR') == 0


def test_flipped_conversion():
rates = [('USD', 'EUR', .74), ('USD', 'JPY', 145.949)]
assert convert(rates, value=1,
from_string='EUR', to_string='USD') == 1.35


def test_multiple_conversions():
rates = [('USD', 'EUR', .74),
('USD', 'JPY', 145.949),
('USD', 'CAD', 1.21)]
assert convert(rates, value=500,
from_string='USD', to_string='EUR') == 370
assert convert(rates, value=500,
from_string='EUR', to_string='USD') == 675.68
assert convert(rates, value=500,
from_string='USD', to_string='JPY') == 72974.5
assert convert(rates, value=500,
from_string='JPY', to_string='USD') == 3.43
assert convert(rates, value=500,
from_string='USD', to_string='CAD') == 605


def test_exception_check():
rates = [('USD', 'EUR', .74),
('USD', 'JPY', 145.949),
('USD', 'CAD', 1.21)]
assert exception_check(rates, value=500,
from_string='USD', to_string='EUR') == 370
assert exception_check(rates, value=500,
from_string='USD', to_string='FART') == (
"Error message")
assert exception_check(rates, value=500,
from_string='ABC', to_string='DEF') == (
"Error message")