TedLawson's Blog

GSOC Week 6 Review

TedLawson
Published: 07/12/2023

Accomplishments:
This week I am proud to have completed the conversion of the rest of the archiver test folder from unittest to pytest. If you will recall, two weeks ago I laid the foundation for these changes by removing the unittest based foundation `ArchiverTestBaseCase` - replacing the setup and teardown methods with pytest fixtures, and converting the rest of the methods to helper functions. My goal this week was to finish the conversion of the 38 test modules and remove all elements of unittest, replacing them with their pytest equivalents. By the end of the week I have completed the conversion of all files (over 6000 lines!) and submitted a PR for the changes that was able to pass all CI tests. Not only this, but the test suite runs slightly faster after my changes, and the code coverage has remained the same. 

Challenges:
This week went very smooth - I had a clear objective and with the foundation complete I was able to move quickly through the test files and to convert them. The challenge I hit this week was getting the tests to pass the CI checks, as I had only ran the tests on my local Mac machine. Windows tests ran into some errors that I was not seeing before, but I was able to do some trial and error that got them to work as intended. Additionally, I hit an issue with the socket path names for a test being too long when using the pytest fixture `tmp_dir`:
`
name = tmp_path / "unix-socket"

sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)

> sock.bind(os.path.join(name))

E OSError: AF_UNIX path too long

`

I switched to using tempfile.mktemp which allowed me to set a shorter path name. This passed the test locally, however when I pushed the changes to GitHub I received a warning: "Insecure temporary file. Call to deprecated function tempfile.mktemp may be insecure."  After doing some digging I found that mktemp files are fundamentally insecure, as they do not ensure exclusive access to a file with the temporary name they return. The file name returned by these functions is guaranteed to be unique on creation but the file must be opened in a separate operation. It was suggested to use a CM, tempfile.TemporaryDirectory, as a temporary directory. This directory was automatically cleaned up after exiting the CM, and worked as intended to pass the test and all CI checks.

The week ahead:
As I wrap up the Borg Unittest to Pytest conversion project, I still have a couple PR's left to get merged in. I will work with Thomas, my mentor who oversees Borg, to ensure that the PRs are buttoned up and ready to be merged. I will also prepare for my next project - increasing Vorta's code coverage - by reviewing the current code coverage, identifying areas of the code base that are lacking coverage, with a special focus on unit testing functions and methods as opposed to integration testing.

View Blog Post

Week 5

TedLawson
Published: 07/05/2023

Accomplishments:

This week I continued my work on the archiver folder, and had a couple meetings with my mentor, Manu, to discuss the progress and where to go from here. I was able to complete the conversion of the ArchiverTestCaseBase to pytest by splitting it into helper functions and pytest fixtures, improving on the foundation that I had begun last week. Additionally, I was able to convert half of the tests in the archiver folder to use the new foundation, and I split up the PR's into more manageable sizes such that my other mentor, Thomas, would have an easier time looking through and reviewing the test files. 

Challenges:

The biggest challenge I faced this week was deciding the best way to separate the old ArchiverTestCaseBase into helper functions and pytest fixtures. The approach Manu and I decided on was the path of least change - removing the helper functions from the unittest class but keeping them in the archiver folder `__init__` , and moving the setup and teardown functions into `conftest` as pytest fixtures. Once me and my mentor agreed on the foundation, it was easy to make progress.

The week ahead:

This week, I will finish converting the archiver folder of tests. I have 18 more test files to go, but since the foundation has been set it it just quick work to get them converted one at a time. For each test file, I am running them using the current unittest framework and recording the number of tests, how many pass or get skipped, and the execution time. I am then converting the tests to the new pytest framework and recording the same data to ensure consistency in test completion, as well as to see if there are any improvements in execution time. My goal by the end of the week is to have a completed archiver folder of tests that is all put into one PR and passes the Borg CI tests. This is a lofty goal, but I am confident I can grind it out!

Tune in next week to see how the goals turned out! Thank you for taking the time to read my updates, and have an excellent week!

 

View Blog Post

Week 4 - Finding my Stride

TedLawson
Published: 06/27/2023

Accomplishments:

Xattr tests PR got merged this week, and the Repo tests are completed and waiting on final approval. It feels really good to have these finished up! The biggest accomplishment this week, however, was converting all of the archiver unit test base functions to pytest. These archiver unit test base functions were the groundwork for all 20 test files in the archiver folder, and by getting these converted into pytest fixtures I was able to begin quickly making inroads to the remaining test files still needing conversion to pytest. I was able to get the unit test functions converted to pytest by Tuesday, and then I was able to complete at least one test file each day this week, and even a little extra over the weekend during a long flight! It felt great to move so quickly through these files, and I feel like I am finally finding my stride and keeping to a pace that I can be proud of.

Challenges:

This week saw surprisingly few challenges. One issue I hit, however, was when trying to convert some helper functions from the unittest base to pytest fixtures so they could be used by all the test files. Here is an example of the function that I would need to convert:

def open_archive(self, name):
    repository = Repository(self.repository_path, exclusive=True)
    with repository:
        manifest = Manifest.load(repository, Manifest.NO_OPERATION_CHECK)
        archive = Archive(manifest, name)
    return archive, repository

When I originally tried to convert this to a pytest fixture, I did something like this:

@pytest.fixture()
def open_archive(archiver):
    def archive_and_repository(name):
        repo_path = archiver.repository_path
        repository = Repository(repo_path, exclusive=True)
        with repository:
            manifest = Manifest.load(repository, Manifest.NO_OPERATION_CHECK)
            archive = Archive(manifest, name)
        return archive, repository

    return archive_and_repository

What I realized, however, was that these type of helper functions should not be fixtures at all. Instead, they should be functions placed in a utils module, and imported by the tests. My mentor gave me a good rule of thumb: Fixtures should only be used if there is a specific setup or teardown being preformed,  while helper functions should be instead placed in a utils package.

The week ahead: 

This week I have a meeting with my mentor, Manu, set up for Wednesday morning. I will also be attending the GSoC contributor mid-summer evaluation meeting on Tuesday morning. Other than the two meetings, I will be continuing to work through the rest of the archiver test folder. I am working quite quickly through these and anticipate being finished with 10 of the 20 test files by the end of the week.

Thanks to everyone for reading, and I look forward to updating on my progress again next week!

View Blog Post

Week 3 - A big week of learning!

TedLawson
Published: 06/20/2023

Accomplishments:

This week I made major progress with the repository test files, and also began working on the extended attributes ('xattr') test cases. I found this past week to be very enlightening, as I began to better understand the "why" behind a lot of Pytest concepts. For example, one member of the community taught me to use the built in pytest fixture `tmp_path` for all temp directories and files, as it automatically cleans up after itself and works consistently across all OS's. I also got a better understanding of context managers, a concept that was really tripping me up in week 2. I also feel good about getting more involved with the commentary this week, as both my mentors and a community members pitched in ideas to help me with the draft PRs I've submitted. After a week of solid progress, the repository tests are pretty near completion, and the xattr tests just need a couple finishing touches. The repository tests are almost 1250 lines of code, and has been a lot of work to get to where it is today, so I feel really proud of the work that has been done there this week.

Challenges:

A week would not be complete without some minor setbacks, and this week I certainly had my fair share. at one point I was getting a bit demotivated with the repository tests. I was getting a lot of community feedback on how to make them better, but sometimes the feedback would conflict and I would not be sure how to proceed. With such. big file, making even a small change to one of the fixtures of context managers would take lots of time to refactor across all the tests, and this became very tedious. However, my mentor Manu gave me some really great advice: he told me to start small and just get a couple of tests working before pushing the changes for review. Only after approval should I then refactor all tests to include the changes. He called this method the 'tracer bullet' style, and it really helped improve me speed.

The week ahead:
Repo and xattr tests should be finished up soon, and then I will begin working on converting the archiver folder of test. This folder has a lot of old unittest style tests, so my work is definitely cut out for me! At the end of this week I will get the ball rolling on my second project - implement profile sidebar for Vorta. I will start a FR post in the Vorta community to begin brainstorming what this could look like and thoughts on how it could be implemented. 

 

It has been an incredible week with lots of progress! Thank you all for reading, and I hope to catch you again next week!

 

View Blog Post

Week 2 - Test suite conversion to pytest continues!

TedLawson
Published: 06/13/2023

Accomplishments:

I ended week 1 feeling a little behind in pace, so I worked though the weekend to parameterize two test files: 'item' and 'version'. These tests needed relatively small changes compared to the other files in the test suite, so I knocked them out and had a PR merged by the end of the weekend. This felt good, and led to me starting week 2 on a high note. Unfortunately, this is where my accomplishments ended, as I hit a lot of roadblocks on my next task: repository tests. Oh man, I got caught up a lot here! Lets dive in...

Challenges:

On the surface, the repository tests were a straight forward conversion from Unittest to Pytest. I needed to create a pytest fixture that replicated the unittest setup and teardown functions, then mimic the reopen functionality that closes a repository and reopens the same repo fresh from disk. Finally, I would translate the roughly 1,100 lines of tests to pytest. Unfortunately, things did not go to plan. I was able to get the repository fixture to work, however things went awry when I tried to reopen the repo, as I ended up nesting context managers in a way that was both ugly to read and also did not function as intended. I want to thank my mentors and the community for all the help pointing me in the right direction as I work to rewrite the tests in a way that did not nest the context managers and helped the code execute (mostly) as intended. By Friday, I had completed translating all 1,100 lines from unittest into pytest, however I am still working to ensure the repository fixture and reopen context manager works as intended.

The Week Ahead:

Going into week three I plan on wrapping up the repository tests and begin working on the next tests that need help: xattr, archive, and the archiver commands folder of tests. I certainly have my work cut out for me, but thanks to my supportive mentors and a wonderful community of helpers, I am confident I will continue to make solid progress.

Thank you all for taking the time to read my blog, and I look forward to updating you again next week!
 

View Blog Post