Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add unit tests for the functions in utils.py #63

Merged
merged 4 commits into from
Feb 19, 2018
Merged

Add unit tests for the functions in utils.py #63

merged 4 commits into from
Feb 19, 2018

Conversation

Shashi456
Copy link
Contributor

@Shashi456 Shashi456 commented Feb 17, 2018

Fixes #6

These are just very basic unit tests , which is my understanding of them. Since we are just checking each module individually and seeing if they do the job they are supposed to do. Also another thing i wanted to ask is how could i go about writing tests for functions which had no parameters, should i just check the existence of what has been returned? Thanks for your help.

@marco-c I will clean up the code and use tempfile in the upcoming commit, this was just for a basic check to see if you were expecting similar unit tests.

@@ -0,0 +1,3 @@
{
"test_utils.py::test_answer": true
Copy link
Contributor

@poush poush Feb 17, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, I think this file should be in the .gitignore.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, and it should also be removed from the PR.

from keras.preprocessing.image import load_img, img_to_array


def mkdir(dir_name):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The functions that need to be tested should not be here.

@marco-c
Copy link
Owner

marco-c commented Feb 17, 2018

Also another thing i wanted to ask is how could i go about writing tests for functions which had no parameters, should i just check the existence of what has been returned?

For functions that require the data directory to exist, don't write any test.
For other functions with no parameters (e.g. get_bugs), just make some basic assertion on the result.

@marco-c
Copy link
Owner

marco-c commented Feb 17, 2018

These are just very basic unit tests , which is my understanding of them. Since we are just checking each module individually and seeing if they do the job they are supposed to do.

Yes, this is what we should do.

@marco-c
Copy link
Owner

marco-c commented Feb 17, 2018

@marco-c I will clean up the code and use tempfile in the upcoming commit, this was just for a basic check to see if you were expecting similar unit tests.

OK, let me know when the PR is ready and I'll review it.

@Shashi456
Copy link
Contributor Author

@marco-c So i've written basic tests for 6 functions, just asserting the existence of the objects in case of functions with no specific parameters. For writing a couples_generator, getImageGenerator there is image_test or image_train so i have written no function for the same.

def test_mkdir():
direc_path = os.path.dirname(os.path.realpath(__file__)) + "test"
utils.mkdir(direc_path)
assert(os.path.exists(direc_path))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can assert that this is a directory.
Also, you can test calling it again to check that it doesn't fail when the directory already exists.

assert(os.path.exists(direc_path))


label = {}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure you need to define this globally.


def test_read_labels():
labels = utils.read_labels(file_name='labels.csv')
assert('labels' in locals() or 'labels' in globals())
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assertion is strange. Just assert that labels is not null and that it is a dictionary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i was just asserting the existence of the variable

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have defined it at line 15, so it clearly exists 😄

def test_write_labels():
utils.write_labels(label, file_name='test.csv')
fname = os.path.dirname(os.path.realpath(__file__)) + "\\test.csv"
assert(os.path.exists(fname))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also assert that you can use read_labels to read the labels back.

assert(os.path.exists(fname))


images = {"Image.png": [23434, 324124]}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is unused.


def test_load_image():
img = utils.load_image("Image.png")
assert(img)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert that this is a numpy 2x2 array


def test_get_bugs():
Object = utils.get_bugs()
assert(Object)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert that this is a list

def test_balance():
Sample = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
it = utils.balance(Sample)
assert(it)
Copy link
Owner

@marco-c marco-c Feb 18, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can actually assert what balance returns here and not just check that it is not null.

@marco-c
Copy link
Owner

marco-c commented Feb 18, 2018

For writing a couples_generator, getImageGenerator there is image_test or image_train so i have written no function for the same.

I'm not sure what you mean here, can you expand?

@marco-c
Copy link
Owner

marco-c commented Feb 18, 2018

Nit: Can you put the tests in the same order as the functions of test_utils.py?

@marco-c
Copy link
Owner

marco-c commented Feb 18, 2018

Also, don't forget to use tempfile to create the temporary directory where you store the temporary test files.

@marco-c marco-c changed the title [#5] Add unit tests for the functions in utils.py Add unit tests for the functions in utils.py Feb 18, 2018
@Shashi456
Copy link
Contributor Author

@marco-c I have added temporary directory to the unit tests wherever I am making a directory or a file. I have also made other minor changes you asked me to do. I had two doubts though, What is balance returning? and I was getting a row index out of range error while reading the written labels do you have any idea what could cause it?



def test_get_bugs():
Object = utils.get_bugs()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: rename Object to bugs.

d = TemporaryDirectory()
direc_path = os.path.join(d.name + "\\test")
utils.mkdir(direc_path)
assert(os.path.isdir(direc_path))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Second part from #63 (comment)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@marco-c Instead of writing a test for it , would it not make more sense to change the mkdir function to check if a directory with the same name exists and not make it if it does? since the function the doesnt return any error message it is pretty hard to assert on anything . If some error message were returned i could assert on the same .

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to add an assertion, the assertion is implied in the fact that utils.mkdir doesn't throw an exception.



def test_load_image():
img = utils.load_image("Image")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file doesn't exist in the repository, so I'm not sure the test will pass.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@marco-c earlier i had the load_image function in the file and i was using a random dictionary to just check if the code was working, Because an empty file name would result in a parameter not declared error. Should i remove the test ?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can add a parent_dir argument to load_image, with the default being data_resized.
Then in the test you can create a fake image in the temporary directory, pass the temporary directory as parent_dir to load_image and then assert that the image is loaded as a 2x2 numpy array with the correct dimensions.

@marco-c
Copy link
Owner

marco-c commented Feb 19, 2018

What is balance returning?

You can see the function implementation or the callers of the functions to understand. If you can't figure it out, please remove the current test_balance and file a follow-up issue to add a test for balance.

and I was getting a row index out of range error while reading the written labels do you have any idea what could cause it?

I'm not sure, as I haven't seen what you were trying to do. If you can't figure it out, please file a follow-up issue to add the test.

@marco-c
Copy link
Owner

marco-c commented Feb 19, 2018

Please also update the .travis.yml file to actually run the tests.

@marco-c
Copy link
Owner

marco-c commented Feb 19, 2018

I've noticed there's a nice pytest feature that you can use instead of manually using tempfile: https://docs.pytest.org/en/latest/tmpdir.html.

@Shashi456
Copy link
Contributor Author

@marco-c i've made all the minor changes you asked me to, i have removed the balance test and will open a pr for the same, because balance seems to be interacting with Couples-generator but we aren't writing tests for functions which need the data directory. One last thing is the error in the Travis-cl build it is giving an image not found error with the Load_image test, while I am able to pass the test successfully on my pc. Any Thoughts?

@marco-c
Copy link
Owner

marco-c commented Feb 19, 2018

@marco-c i've made all the minor changes you asked me to

It seems you haven't done #63 (comment) and #63 (comment).

i have removed the balance test and will open a pr for the same, because balance seems to be interacting with Couples-generator but we aren't writing tests for functions which need the data directory.

The balance function is generic, it doesn't require CouplesGenerator to work. Anyway yes, please open an issue to add a test for this function and an issue for each function in utils.py that isn't tested yet.

One last thing is the error in the Travis-cl build it is giving an image not found error with the Load_image test, while I am able to pass the test successfully on my pc.

Doing #63 (comment) will fix the problem.

@Shashi456
Copy link
Contributor Author

@marco-c i did modify both the load image file with the parent directory and try it with both temporary and an actual directory. I will look further into, thankyou.

@marco-c
Copy link
Owner

marco-c commented Feb 19, 2018

@marco-c i did modify both the load image file with the parent directory and try it with both temporary and an actual directory. I will look further into, thankyou.

Also don't download the image from the network, it's not great for unit tests (what if the image is removed from the website? The tests will start failing). Create a fake image using PIL.

os.mkdir('data_resized')
fake_img = np.random.rand(30, 30, 3) * 255
img = Image.fromarray(fake_img.astype('uint8')).convert('RGBA')
img.save(".\data_resized\Image.jpg", "JPEG")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't specify the format, it's automatically detected from the file extension.

Review Changes

Review Changes

Review Changes

Review Changes
@Shashi456
Copy link
Contributor Author

@marco-c i will open the balance PR as soon as this is merged, i have done all changes you've asked me for . Thankyou

@marco-c
Copy link
Owner

marco-c commented Feb 19, 2018

@marco-c i will open the balance PR as soon as this is merged, i have done all changes you've asked me for . Thankyou

I still don't see #63 (comment) 😄

Also, in test_load_image you should use a temporary directory and not manually create and delete data_resized, which would mess the working directory of anyone which runs the tests.

def test_load_image():
os.mkdir('data_resized')
fake_img = np.random.rand(30, 30, 3) * 255
img = Image.fromarray(fake_img.astype('uint8')).convert('RGBA')
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use Image.new instead of creating a numpy array and then convering it into an image.

d = TemporaryDirectory()
file_path = os.path.join(d.name + "\\test.csv")
utils.write_labels(label, file_name=file_path)
assert(os.path.exists(file_path))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remember to file an issue about adding a test that writes labels and then reads them back.


def test_mkdir():
d = TemporaryDirectory()
direc_path = os.path.join(d.name + "\\test")
Copy link
Owner

@marco-c marco-c Feb 19, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're calling os.path.join with a single string, which is basically useless.
Either do os.path.join(d.name, 'test') or d.name + '/test'.

import numpy as np
from tempfile import TemporaryDirectory
from autowebcompat import utils
from PIL import Image
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sort the imports in this way:

  1. Built-in modules;
  2. Modules from third-party libraries;
  3. Our modules.

@Shashi456
Copy link
Contributor Author

Shashi456 commented Feb 19, 2018

@marco-c do you necessarily want the new pytest feature and not the Temporary Directory () way?

.travis.yml Outdated
@@ -6,3 +6,4 @@ install:
- pip install -r test-requirements.txt
script:
- flake8 .
- pytest ./tests/test_utils.py
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is going to execute test_utils.py only, please make it run any test that is in the tests directory, so we don't have to update this line the next time we add a test.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't forget about this, @Shashi456

@marco-c
Copy link
Owner

marco-c commented Feb 19, 2018

@marco-c do you necessarily want the new pytest feature and not the Temporary Directory () way?

The pytest feature is nicer, so I would prefer it. If you can't, please file an issue for someone else to do it.

@Shashi456
Copy link
Contributor Author

Shashi456 commented Feb 19, 2018

Would you want the PR's to be referenced to this? @marco-c

@marco-c
Copy link
Owner

marco-c commented Feb 19, 2018

Would you want the PR's to be referenced to this? @marco-c

Do you mean the issues? Yes



def test_read_labels():
labels = utils.read_labels(file_name='labels.csv')
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create a fake labels.csv file in a temporary directory, so you can assert more things about the result.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, don't do it, we'll do it as part of the other test that writes and reads labels.

img = Image.new("RGB", (30, 30))
img.save(d.name + "/Image.jpg")
img = utils.load_image("Image.jpg", d.name)
assert(isinstance(img, np.ndarray))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can assert the dimensions of the numpy array too.

Copy link
Owner

@marco-c marco-c left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I see you have filed follow-up issues. I'm marking them good first bugs for newcomers, but since they are follow-ups to your PR, you can take them if you want (just say so in the issue if you do).

@marco-c marco-c merged commit 7396079 into marco-c:master Feb 19, 2018
@propr
Copy link

propr bot commented Feb 19, 2018

Please provide your feedback on this pull request here.

Privacy statement: We don't store any personal information such as your email address or name. We ask for GitHub authentication as an anonymous identifier to account for duplicate feedback entries and to see people specific preferences.

marxmit7 pushed a commit to marxmit7/autowebcompat that referenced this pull request Jan 18, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants