Skip to content

The official repository for Babel, the Python Internationalization Library

License

Notifications You must be signed in to change notification settings

Radu-Nicolae/babel-sep

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Assignment 1 - Testing

The current project is the sum of all work of Group 7's project for the first assignment of the Software Engineering Processes (XB_0089) course.

The presentation of the project in Google Slides is available here.

Table of contents

Task Sections
3.1. Project Choice Project choice
3.2. Coverage Measurement Executing (external) coverage tool
4.1 Execution of existing coverage measurement tool
Instrumentation
4.2 Instrumentation of functions for coverage measurement
Executing (our own) coverage tool
4.3 Functionality of the instrumentation for coverage measurement
3.3 Coverage Improvement Tests overview
4.4 Creation/enhancement of new tests
4.5 Functionality of the new/enhanced tests
Overall coverage improvement
4.6 Effectiveness of each new/enhanced test in improving coverage
4.7 Overall improvement in coverage
3.4 Report README.md

Project choice

The project of choice is Babel. Latest release of the project as of Jun 11th, 2024, is v2.15.0.

_"Babel is a Python library that provides an integrated collection of utilities that assist with internationalizing and localizing Python applications (in particular web-based applications.)"

from Babel's README.md

Requirement Babel
Hosted on GitHub Repository Link
Open Source License BSD-3-Clause
Automated unit tests Test Directory
Existing branch coverage < 100% 89%
Contributors 150
Lines of code 17 KLOC
11 KLOC (excluding tests)

Executing (external) coverage tool

4.1 Execution of existing coverage measurement tool

We calculate the project's total coverage using the coverage.py tool. We first set up the project's environment, following its documentation and install the necessary dependencies.

Setup

make setup_sep

Or without make:

virtualenv venv > /dev/null
cp -r sep_coverage venv/lib/python3.12/site-packages/
(. ./venv/bin/activate && pip install -r requirements.txt && export PYTHONPATH=$(realpath venv/lib/python3.12/site-packages/) && python setup.py import_cldr && pip install --editable .) > /dev/null 2>&1

➡️ Skip setup explanation

A virtual environment venv is required to run coverage. We first installed virtualenv and pip using each operating system's package manager (either brew or pacman).

After that, we copy the local package sep_coverage (created by ourselves) to the virtual environment's site-packages directory (further expanded in Own coverage tool section).

⚠️ WARNING: The setup assumes that the latest version of python (3.12) is installed on the system, as well as the virtualenv and pip packages. If this is not the case, the setup will fail.

The project's documentation was followed to install the project's dependencies and import the CLDR (Common Locale Data Repository) data. However, it does not mention the need to set the PYTHONPATH environment variable to the virtual environment's site-packages directory. This is to ensure that some tests that create a separate virtual environment will maintain the correct path to the sep_coverage package. Also, there are some external packages that need to be installed.

The entire process is summed up in the setup_sep target of the Makefile.

Proof Makefile

Running

make coverage_extern

Or without make:

. ./venv/bin/activate && coverage run --omit='sep_coverage/*','tests/*' -m pytest && coverage report > coverage_report.txt
cat coverage_report.txt

➡️ Skip running explanation

We first enter the python virtual environment by sourcing the activate script in the venv directory.

The coverage.py tool has a run command that runs the coverage test and a report command that generates a report of the coverage in plain text. These two commands will represent our two-step process in running the coverage.

The run command takes one argument, --omit, which is used to specify which files to omit from the coverage report and another argument -m pytest to run the tests using the pytest module. We are using pytest to run the tests that generate the coverage for the project. Pytest is also the testing framework used by the project itself.

IMPORTANT: We omit the files in the sep_coverage/ package and the tests/ directory from the coverage report. This is because the sep_coverage package is our own coverage tool, and the tests directory contains are not of interest for the purposes of coverage, as the tests themselves generate the coverage. We are only interested in the coverage of the babel package.

Finally, we generate the coverage report using the report command.

The entire process is summed up in the coverage_extern target of the Makefile.

Proof Makefile

Results

The entire result file, containing coverage data for every single file in the project, can be found in report/extern_coverage_before.txt.

Total Statements Total Missed Coverage
4526 490 89.17%

Executing (our own) coverage tool

4.3 Functionality of the instrumentation for coverage measurement

We create our own coverage tool, sep_coverage, using manual instrumentation to measure the coverage of some parts of the project. The tool is documented under sep_coverage/README.md.

⚙️ Prerequisite: Setup (only has to be done once)

make coverage_sep

or without make:

. ./venv/bin/activate && python3 sep_coverage.py

➡️ Skip to results

Breakdown of the tool

The sep_coverage tool is built as a python package under the sep_coverage/ directory. Because of this, it must be copied under the virtual environment's site-packages directory to be imported by the project.

At each instrument() call, the tool stores the identifier of the statement in a set mapped to each entity (file, class, function, method) that the statement belongs to. Each entity is indexed in sep_coverage/program_entity.py, containing a range of statements that it covers.

After execution, we can use the set of each entity to calculate how many statements were reached, as the length of the set. The total number of statements is equal to the upper bound of the range, minus the lower bound plus one.

We can use this information to calculate the coverage of each entity, given the following formula, where C = coverage, M = total statements, N = total missed statements:

formula

When the tool is run, the coverage test is executed, and then the coverage data is printed to stdout.

Methodology of instrumentation

Each team member look at the coverage report of generated by coverage.py (specifically the html report created by running coverage html) and choose at least two functions or methods with low coverage to instrument. The html coverage report page provides useful information, such as which exact lines are not covered by the tests.

Each function, method, class (Entity) is instrumented by the following syntax:

import sep_coverage

sep_coverage.instrument([ENTITY_FLAG_1, ENTITY_FLAG_2, ...], instrument_id)

This method allows us to store the following coverage information for each instrumented line of code:

  • Which entity the line belongs to (file, class, function or method)
  • The instrument identifier of the line
  • Whether the line was executed during the tests

Results

The coverage report generated by our tool, before the coverage improvement can be found in report/sep_coverage_before.txt.

Total Statements Total Missed Coverage
57 25 56.14%

Since we are only instrumenting a small part of the project, the coverage is expected to be low. We specifically targeted parts of the code that were not covered by the tests, in order to work on improving coverage in the next step.


Instrumentation

4.2 Instrumentation of functions for coverage measurement

Member Entities Instrumented Total lines of code
Daniel FixedOffsetTimezone
_locales_to_names()
14
Gleb get_timezone()
_get_time()
26
Mateusz _get_tzinfo()
_get_tzinfo_or_raise()
_get_tzinfo_from_file()
49
Radu format_date()
__str__()
38

Instrumentation proofs

Daniel Halasz

_locales_to_names() _FixedOffsetTimezone

Mateusz Kwiatkowski

_get_tzinfo _get_tzinfo_or_raise _get_tzinfo_from_file

Radu Nicolae

format_date() __str()__

Gleb Mishchenko

get_timezone() _get_time()

Measurement proofs

Coverage measurement

Coverage improvement

Tests overview


4.4 Creation/enhancement of new tests

Below is the evidence (code) that each student created/enhanced 2 tests, repsectively to their instrumented functions.

Daniel Halasz

_locales_to_names()

Mateusz Kwiatkowski

test_get_tzinfo test_get_tzinfo_from_file

Radu Nicolae

format_date()

Gleb Mishchenko

get_timezone()

4.5 Functionality of the new/enhanced tests

General approach

Each team member after instrumenting their respective functions, and after looking at the coverage report of generated by coverage.py implemented specific tests to increase the coverage of these functions.

Each function got tested in a distinct, specific way, unique to its purpose. For example in tests_mateusz.py the coverage of the _get_tzinfo_or_raise() function is achieved by making sure certain errors and assertions are raised (or not).

    with pytest.raises(LookupError):
        _helpers._get_tzinfo_or_raise("Continent/City")

    tzinfo = _helpers._get_tzinfo_or_raise("America/New_York")
    assert tzinfo is not None
    assert tzinfo.zone == "America/New_York"

This method allowed each team member to successfully increase the overall coverage of their chosen functions, as, for example, more statements and if-else branches are reached after implementing the tests.

The correctness of our tests is presented with the following screenshot, after running pytest with the new tests.

pytest

Overall coverage improvement


4.6 Effectiveness of each new/enhanced test in improving coverage

The coverage report generated by our tool before the coverage improvement is summarized in the following table

Total Statements Total Missed Coverage
57 25 56.14%

Since we specifically targeted parts of the code that were not covered by the general tests, and each team member managed to increase their instrumented function coverage almost to its fullest, we report the following coverage after implementing the enhanced tests

Total Statements Total Missed Coverage
57 4 92.98%

This improvement is also showcased in the following screenshot. After running the suggested tool, coverage.py, on the initial directory and the directory with the ehnanced tests, we compared the two reports with diff.

effectiv

4.7 Overall improvement in coverage

With this we conclude that the total overall improvement that we reached amounted to 1.12%. The following screenshots of running coverage.py without and with the enhanced tests show the total coverage measured before and after.

Before

before

After

after

About

The official repository for Babel, the Python Internationalization Library

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Python 99.3%
  • Other 0.7%