Need help understanding the results of the unit function

I want to get Limit of the following function at $Tto 0$.
$$
Eig=frac{8 (eta +J sinh (2 beta eta ) sinh (2 beta J)+eta cosh (2 beta eta ) cosh (2 beta J))}{eta Z^2}
$$

where $Z=2 (cosh (2 beta eta )+cosh (2 beta J))$, $eta =sqrt{B^2+J^2}$, and $beta =frac{1}{T}$. Both $J, B$ are reals.

I used

Z = 2 (Cosh(2 β J) + Cosh(2 β η));
η = Sqrt(B^2 + J^2);
β = 1/T;
Eig = (8 (η + η Cosh(2 β η) Cosh(2 β J) + 
    J Sinh(2 β η) Sinh(2 β J)))/(Z^2 η)
Limit(Eig, T -> 0)

But I can’t understand the output.

reference request – Is realization of unit disk graphs hard?

It is known that recognizing a unit disk graph is NP-hard (1).

However, the paper does not mention how hard is the realization problem.

I have looked up several references (2)(3)(4). None of the papers answer whether the following problem is NP-hard:

Given a unit disk graph $G = (V,E)$, find a configuration of a set
$mathcal{D}$ of disks, such that the intersection graph
$G(mathcal{D})$ of $mathcal{D}$ is isomorphic to $G$.

The difference between this problem and the recognition problem is that the input of this problem is guaranteed to be a unit disk.

Is there any study that shows the complexity of the above problem? I expect it to be NP-hard, but I am yet to find a full proof.

design patterns – What to do with a legacy code base with no unit tests and complex architectural structure

I have been working for my company for almost a year now and been primarily focused on adding features and maintaining two 15+-year-old WPF Projects and one 20+-year-old WinForms Project. The codebases have absolutely no unit testing, the philosophy is that every engineer should be able to write bug-free code. The WPF projects are big and follow DDD and try to follow MVVM unless it becomes inconvenient. It does not follow established design patterns so features are added any way the engineer sees fit. There are no code reviews so it’s not hard to see how new members of the team could struggle with the codebase as I have these last couple of months. So I wanted to what would be the most valuable course of action for me to do given the following metrics using Microsofts’ FxCop analyzers.

WPF Project 1

enter image description here

WPF Project 2

enter image description here

I’m overwhelmed by the numbers and don’t know what problem should be the main priority. We have some very high numbers of cyclomatic complexity that would make unit testing really challenging to do. We have some high coupling numbers which beg for refactoring. There are endless places where design patterns can be applied to clean up the code. My main priority now is to fix some of the codebase problems but don’t know what would bring the most value. I feel inclined to just start unit testing like a mad man.

What do you guys think should be the next step after looking at the metrics? Should I start unit testing before refactoring? Are unit tests overrated and adopt my company philosophy and just focus on addressing the cyclomatic complexity and coupling problems? I’m I even asking the right questions here?

Just looking for a bit of guidance as this is a huge challenge for me. I work with a team but taking this initiative on my own with only 6 years of experience, so there is not enough time or money to really address everything. I also realize that whatever the next step is it will include convincing my boss, so any tips on that would also be appreciated.

labels – When to move on to the next unit prefix, e.g. 900 kB vs 0.9 MB

Is there any established standard or research about what the cut-off point should be for moving to the next unit prefix e.g. moving from “kilo” to “mega”?

I assume it may depend on the unit itself, so I’m specifically asking about bytes (or bits), for example when displaying download progress / remaining.

One approach I’ve seen is moving as soon as it goes above 1000 (or 1024), e.g. 1000 kbit becomes 1 Mbit. However, it’s not uncommon to cut off before that: I’ve seen e.g. camera manuals say “0.8 MB” rather than “800 KB” for the size of a photo.

c# – Should I have “shouldfail” unit test and “shouldpass” for all methods in TDD?

Here is my class library code which I have C# and xUnit.

namespace XUnitSample.ClassLib
{
    public class DataAccess : IDataAccess
    {
        public void AddPersonToPeopleList(List<Person> people, Person person)
        {
            // TDD: 01 - Write a unit test which 'shouldfail'
            // If the 'shouldfail' unit test you wrote fail as expected, 
            // then your unit test is 'passed'.
            //people.Add(person);

            // TDD: 02 - Write a unit test which 'shouldpass'.
            // If the 'shouldpass' unit test you wrote fail as expected, 
            // then your unit test is 'passed'.
            people.Add(person);
        }

    }
}

And for my xUnit, I have one test class with 2 unit tests method.

public class DataAccessTest
{
    (Fact) 
    // TDD: 01 - Write a unit test which "shouldfail"
    // If the "shouldfail" unit test you wrote fail as expected, 
    // then your unit test is "passed".
    public void AddPersonToPeopleList_ShouldFail()
    {
        // Arrange
        var newPerson = new Person() { Id = 1, FullName = "John" };
        var people = new List<Person>();

        // Act
        var dataAccess = new DataAccess();
        dataAccess.AddPersonToPeopleList(people, newPerson);

        // Assert
        // If count is not 1, unit test is 'passed'
        Assert.True(people.Count != 1);

        // If people does not contain new person, unit test is 'passed'
        Assert.DoesNotContain<Person>(newPerson, people);

    }

    (Fact)
    //TDD: 02 - Write a unit test which 'shouldpass'.
    // If the 'shouldpass' unit test you wrote fail as expected, 
    // then your unit test is 'passed'.
    public void AddPersonToPeopleList_ShouldPass()
    {
        // Arrange
        var newPerson = new Person() { Id = 1, FullName = "John" };
        var people = new List<Person>();

        // Act
        var dataAccess = new DataAccess();
        dataAccess.AddPersonToPeopleList(people, newPerson);

        // Assert
        // If count == 1, unit test is 'passed'
        Assert.True(people.Count == 1); 

        // If people contain new person, unit test is 'passed'
        Assert.Contains<Person>(newPerson, people);
    }
}

Is this what it means by applying TDD principles of writing a unit test which shouldfail first and then write unit test which shouldpass?

unit testing – Is the self-shunt pattern the same as stubbing in TDD?

I am reading the book TDD by Example and one of the patterns demonstrated was the self-shunt pattern.

Basically, if I am not mistaken, if I have a test like this:

test("list of users should receive a new user"), () => {
  const user = new User()
  const listOfUsers = new ListOfUsers()
  listOfUsers.insert(user)
}

Then, the only way to know if listOfUsers actually received the user, is to stub it, correct?

class ListOfUsersStub {
  constructor () {
    this.users = ()
  }

  insert (user) {
    this.users.push(user)
    return this.users
  }
}

then I can test it so:

test("list of users should receive a new user"), () => {
  const user = new User()
  const listOfUsers = new ListOfUsers()
  const result = listOfUsers.insert(user)
  expect(result.users).toContain(user)
}

Is this the same as the self shunt pattern? Or am I missing something?

Thanks

database – Is splitting unit tests from integration test with mocks worth the effort (in nodejs)?

Well consider a relative simple server for a SPA application. Written in nodejs with express and knex as backends.

Now if we do it properly each function will have unit tests (as they are always all visible to the end user). But besides of the choice of what function to create unit test for, is abstracting away the database actually worth the effort?

A simple function might look like:

function doSomething(request_object, response_object) {
    request_data = analyze_request();
    db_data = grabFromDatabase(request_data); //this is often just a knex query.
    result = reformatDBQuery(db_data);
    response_object.give_response(result);
}

Now to do it properly one would create mocks/stubs that either mock knex library. Or mock the interface methods we use ourselves.
Both cases require a lot of writing, often so much as almost recreating the library ourselves.

The other option is to create only stubs for the exact function arguments required: but this would make tests quite brittle and the most common error I experience (by a large margin) wouldn’t really be catched with this: Unexpected argument values in some function that do work but give nonsensical results that fail at another place.

So a tertiary option is possible: actually just use a database for testing. However this means the unit test is no longer a unit test. And it’s really just an integration test. As this is about the only “complexity” that isn’t trivial code it hence makes little sense to even have unit tests (the other tests are so trivial they can easily be added to the integration tests).

Especially since “launching” a real database connection in javascript is quite fast anyways. And writing mocks for every possible function in a library very, very time consuming.

So what do others do, especially with regards to “simple servers” where complexity is only found in database calls?

EDIT, to clarify, I understand the need for a unit test above integration tests. I wonder however what people do in practice given time constraints typically visible. And wonder how in reality people sidestep the problem of very very time consuming mocks.

magento2 – How to write unit test for prepareDataSource when call store return null?

I am writing unit test prepareDataSource function in Magento 2. In the prepareDataSource() function in Price class.

Option 1: If I using $currency = $this->getCurrency($item(‘store_currency_code’)); in the prepareDataSource() function. It return null data.

Option 2: If I using $currency = $this->getBaseCurrencyCode(); in the prepareDataSource() function. and using storeMock Price::class,(‘_storeManager’ => $this->_storeMock, ‘context’ => $contextMock) in the PriceTest class. It return Error Error : Call to a member function getBaseCurrencyCode() on null

Please help me, How to fix to return the price result as expect result?
Can I using option_2? How to do that?

My class PriceTest class as below:

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

namespace MyAppSaleReportsTestUnitUiComponentListingComlumnsInvoiceReport;

use MagentoFrameworkTestFrameworkUnitHelperObjectManager;
use MyAppSaleReportsUiComponentListingColumnsInvoiceReportPrice;

/**
 * Class PriceTest
 */
class PriceTest extends PHPUnitFrameworkTestCase
{
    /**
     * @var Price
     */
    protected $model;

    /**
     * @var Currency|PHPUnit_Framework_MockObject_MockObject
     */
    protected $currencyMock;

    protected $priceMock;

    protected $_storeMock;

    protected $storeManager;

    protected function setUp()
    {
        $objectManager = new ObjectManager($this);
        $contextMock = $this->getMockBuilder(MagentoFrameworkViewElementUiComponentContextInterface::class)
            ->getMockForAbstractClass();
        $processor = $this->getMockBuilder(MagentoFrameworkViewElementUiComponentProcessor::class)
            ->disableOriginalConstructor()
            ->getMock();
        $contextMock->expects($this->never())->method('getProcessor')->willReturn($processor);
        $this->currencyMock = $this->getMockBuilder(MagentoDirectoryModelCurrency::class)
            ->setMethods(('format'))
            ->disableOriginalConstructor()
            ->getMock();
        /*$this->_storeMock = $this->getMockBuilder(MagentoStoreModelStore::class)
            ->setMethods(('getBaseCurrencyCode'))
            ->disableOriginalConstructor()
            ->getMock();*/

        //'_storeManager' => $this->_storeMock, '_priceCurrency' => $this->priceMock
        $this->model = $objectManager->getObject(
            Price::class,
            ('_currency' => $this->currencyMock, 'context' => $contextMock)
        );
    }

    public function testPrepareDataSource()
    {
        $itemName = 'price';
        $oldItemValue = 'oldItemValue';
        $expectPrice = '$10,000';

        $currency = "USD";
        $dataSource = (
            'data' => (
                'items' => (
                    (
                        $itemName => $oldItemValue,
                        'store_currency_code' => 'USD',
                        'price' => 10000
                    )
                )
            )
        );

        $this->model->setData('name', $itemName);
        $dataSource = $this->model->prepareDataSource($dataSource);
        $this->assertEquals($expectPrice, $dataSource('data')('items')(0)($itemName));
    }
}

========================================

Price class extend BaseColumn class:

namespace MyAppSaleReportsUiComponentListingColumnsInvoiceReport;

<?php

class Price extends MyAppSaleReportsUiComponentListingColumnsBaseColumn
{
    /**
     * Prepare Data Source
     *
     * @param array $dataSource
     * @return array
     */
    public function prepareDataSource(array $dataSource)
    {
        if (isset($dataSource('data')('items'))) {
            $fieldName = $this->getData('name');
            foreach ($dataSource('data')('items') as & $item) {
                $currency = $this->getCurrency($item('store_currency_code'));
                //$currency = $this->getBaseCurrencyCode();
                $price = $item('price');
                $item($fieldName) = $this->_priceCurrency->format($price, false, 2, $this->getStore(), $currency);
            }
        }

        return $dataSource;
    }
}

BaseColumn class:



namespace MyAppSaleReportsUiComponentListingColumns;

use MagentoFrameworkViewElementUiComponentFactory;
use MagentoFrameworkViewElementUiComponentContextInterface;
use MagentoFrameworkPricingPriceCurrencyInterface;
use MagentoDirectoryModelCountryFactory;
use MagentoStoreModelStoreManagerInterface;
use MagentoDirectoryModelCurrencyFactory;

class BaseColumn extends MagentoUiComponentListingColumnsColumn
{

    /**
     * Column name
     */
    const NAME = 'name';
    private $_report;
    /**
     * @var StoreManagerInterface
     */
    private $_storeManager;

    /**
     * @var CurrencyFactory
     */
    private $_currency;
    protected $_priceCurrency;
    protected $_countryFactory;

    protected $_storeResolver;
    /**
     * @param ContextInterface $context
     * @param UiComponentFactory $uiComponentFactory
     * @param MyAppSaleReportsModelReport $report
     * @param MagentoStoreModelStoreManagerInterface $storeManager
     * @param array $components
     * @param array $data
     */
    public function __construct(
        ContextInterface $context,
        UiComponentFactory $uiComponentFactory,
        MyAppSaleReportsModelReport $report,
        PriceCurrencyInterface $priceCurrency,
        CountryFactory $countryFactory,
        StoreManagerInterface $storeManager,
        CurrencyFactory $currencyFactory,
        MagentoStoreModelStoreResolver $storeResolver,
        array $components = (),
        array $data = ()
    ) {
        parent::__construct($context, $uiComponentFactory, $components, $data);
        $this->_report = $report;
        $this->_priceCurrency = $priceCurrency;
        $this->_countryFactory = $countryFactory;
        $this->_storeManager = $storeManager;
        $this->_currency = $currencyFactory->create();
        $this->_storeResolver = $storeResolver;
    }

    /**
     * @return StoreInterface
     * @throws NoSuchEntityException
     */
    protected function getStore()
    {
        $currentStore = $this->_storeResolver->getCurrentStoreId();
        return $this->_storeManager->getStore($currentStore);
    }

    /**
     * Convert money by currency
     * @param $money_value
     * @return float
     * @throws NoSuchEntityException
     */
    protected function convertMoney($money_value)
    {
        $currencyCode = $this->getStore()->getCurrentCurrencyCode();
        return $this->_priceCurrency->convert($money_value, $this->getStore(), $currencyCode);
    }

    protected function getCurrency($currencyCode)
    {
        return $this->_currency->load($currencyCode);
    }

    /**
     * Get store base currency code
     *
     * @return string
     */
    public function getBaseCurrencyCode()
    {
        return $this->_storeManager->getStore()->getBaseCurrencyCode();
    }
}

Thank you so much,
BienHV

c# – In Memory Database in Unit tests, isolate the tests

I have stumbled across these unit tests in a code review that are using in memory db:

private DatabaseContext _context;
private Fixture _fixture;

(SetUp)
public void Setup()
{

    _fixture = new Fixture();
    _fixture.Customize(new AutoNSubstituteCustomization());

    var options = new DbContextOptionsBuilder<DatabaseContext>()
    .UseInMemoryDatabase(databaseName: "testdb")
    .Options;
    _context = new DatabaseContext(options);
}

(TearDown)
public void CleanUp()
{
    var context = _context;
    if (context == null || context.Database.ProviderName != "Microsoft.EntityFrameworkCore.InMemory")
    {
        return;
    }

    context.Database.EnsureDeleted();
    _context = null;
}

#region EmptyDB
(Test)
public void Test1()
{
    // Setup
    var logger = _fixture.Freeze<ILogger<UserRepository>>();

    var userRepo = new UserRepository(_context, logger);

    var userViews = new List<UserView>();
    userViews.AddRange(_fixture.CreateMany<UserView>(10));

    // ACT
    userRepo.UpdateUsers(userViews, CancellationToken.None).GetAwaiter().GetResult();

    // ASSERT
    Assert.AreEqual(10, _context.Users.CountAsync().GetAwaiter().GetResult());
}

(Test)
public void Test2()
{
    // Setup
    var logger = _fixture.Freeze<ILogger<UserRepository>>();

    var userRepo = new UserRepository(_context, logger);

    var identityViews = new List<IdentityView>();
    _fixture.Register<IEnumerable<UserView>>(() =>
    {
        return new UserView() { new UserView("fish") };
    });
    userViews.AddRange(_fixture.CreateMany<UserView>(10));

    // ACT
    userRep.UpdateUsers(userViews, CancellationToken.None).GetAwaiter().GetResult();

    // ASSERT
    Assert.AreEqual(10, _context.Users.CountAsync().GetAwaiter().GetResult());
}

As you can see, the tests are using the same in memory db, which I really don’t like. I also don’t like the new UserRepository(_context, logger). Is it a bad practice to use the new-keyword like this?

I would prefer something like this instead:

(Test)
public void Test1()
{
    // Setup
    var provider = RegisterServices();  
    var logger = _fixture.Freeze<ILogger<UserRepository>>();
    var userRepo = provider.GetRequiredService<IUserRepository>();

    var userViews = new List<UserView>();
    userViews.AddRange(_fixture.CreateMany<UserView>(10));

    // ACT
    userRepo.UpdateUsers(userViews, CancellationToken.None).GetAwaiter().GetResult();

    // ASSERT
    Assert.AreEqual(10, _context.Users.CountAsync().GetAwaiter().GetResult());
}

private ServiceProvider RegisterServices((CallerMemberName) string memberName = "")
{
    var services = new ServiceCollection();

    services.AddDbContext<IDatabaseContext, DatabaseContext>(options =>
        options.UseInMemoryDatabase(memberName));

    services.AddPersistence("https://localhost");       

    return services.BuildServiceProvider();
}

As you can see, I have added a RegisterService method that takes the calling test as a parameter, and then uses this to create the inmemorydb. I really like this because you are isolating your tests more this way. I also think it’s cleaner to read.

How would you guys do in this case? Is the first approach the way to go, or is my approach the more “right” way to do it? Or is it another better and more best practice way to do it?

I just want to know your opinions about this and about the two approaches above.

python – Is this a good unit test for testing three types of mappings all at once?

This question is related to my previous two questions, in which I have implemented HashTable, and also SortedListMap and BinarySearchTree. Since the three types of mappings have similar interfaces, if I wrote three separate tests for them there would be lots of boilerplate codes. Instead I decided to write a single test script (using pytest) to test all three at once. It was tricky and took me a lot of time to set up the fixtures correctly, but finally I managed it and all tests were passed.

Summary of the three types of mappings and what I want to do in the test code:

  1. All three types of mappings are subclasses of the abstract base class MutableMapping. They all have the methods __len__, __iter__, __getitem__, __setitem__, __delitem__ required by MutableMapping, so I need to write test classes to test these methods on all three of them.
  2. SortedListMap and BinarySearchTree are also sorted mappings. Although I didn’t make SortedMapping into an explicit abstract base class, as sorted mappings they both have the minimum, maximum, predecessor and successor methods, which needs separate test classes than those mentioned in 1.
  3. I want to test on a small number of fixed inputs as well as a large number of random inputs.
  4. In total I need four test classes: unsorted maps and fixed inputs, unsorted maps and random inputs, sorted maps and fixed inputs, sorted maps and random inputs.

Below is my test code:

import collections
import random
from string import ascii_lowercase
from itertools import product

import pytest
from hash_table import HashTable
from sorted_list_map import SortedListMap
from binary_search_tree import BinarySearchTree

"""Map Classes that we are testing."""

UNSORTED_MAPS = (HashTable, SortedListMap, BinarySearchTree)
SORTED_MAPS = (SortedListMap, BinarySearchTree)


"""Constants and a fixture for testing small fixed inputs.
The keys are deliberately repeated to test whether the maps contain repeated keys.
"""

KEYS = ('A', 'B', 'C', 'C', 'A', 'D', 'E', 'F',
        'G', 'G', 'G', 'H', 'E', 'I', 'A', 'J',
        'K', 'L', 'D', 'J', 'F', 'L', 'B', 'K')

KEY_SET = set(KEYS)
SORTED_KEYS = sorted(KEY_SET)
ITEMS = ((key, i) for i, key in enumerate(KEYS))
DICT_ITEMS = dict(ITEMS).items()
SORTED_ITEMS = sorted(DICT_ITEMS)


@pytest.fixture(scope='class')
def fixed_input_map(request):
    """Return a map of the requested map class with the given fixed items."""
    my_map = request.param(ITEMS)
    return my_map


"""Constants, fixtures and helper functions for testing large random inputs.
The keys are drawn at random from the list of all strings of 3 lowercase letters.
"""

KEY_LEN = 3
POSSIBLE_KEYS = (''.join(chars) for chars in product(ascii_lowercase,
                                                     repeat=KEY_LEN))


@pytest.fixture(scope='class')
def map_pair(request):
    """Return a map of the requested map class and also a python dictionary.
    In the tests, we would compare our maps with the python dicts.
    Since the scope is 'class', this fixture actually return the same
    my_map and python_dict instances for every test within the same test class.
    This means all modifications to my_map and python_dict done by previous tests
    are carried over to later tests.
    """
    my_map = request.param()
    python_dict = {}
    return my_map, python_dict


def random_setitem(my_map, python_dict):
    """Helper function for adding random items into my_map and python_dict.
    Number of added items equals number of possible keys.
    But since there are repeated added keys, not all possible keys are added.
    """
    added_keys = random.choices(POSSIBLE_KEYS, k=len(POSSIBLE_KEYS))
    for i, key in enumerate(added_keys):
        my_map(key) = i
        python_dict(key) = i
    return my_map, python_dict


def random_delitem(my_map, python_dict):
    """Helper function for removing random items from my_map and python_dict.
    Number of removed items is chosen to be 2/3 of the existing items.
    """
    num_dels = len(python_dict) * 2 // 3
    removed_keys = random.sample(python_dict.keys(), k=num_dels)
    for key in removed_keys:
        del my_map(key)
        del python_dict(key)
    return my_map, python_dict


"""Test classes"""


@pytest.mark.parametrize('fixed_input_map', UNSORTED_MAPS, indirect=True)
class TestUnsortedMapFixedInput:
    """Test class for unsorted maps with small fixed inputs."""

    def test_len(self, fixed_input_map):
        """Test the __len__ method."""
        assert len(fixed_input_map) == len(KEY_SET)

    def test_iter(self, fixed_input_map):
        """Test the __iter__method.
        Since we don't care about the ordering, we cast the iterator into a set.
        """
        assert set(key for key in fixed_input_map) == KEY_SET

    @pytest.mark.parametrize('key, value', DICT_ITEMS)
    def test_getitem(self, fixed_input_map, key, value):
        """Test the __getitem__ method for all (key, value) pair."""
        assert fixed_input_map(key) == value

    @pytest.mark.parametrize('key', KEY_SET)
    def test_delitem(self, fixed_input_map, key):
        """Test the __delitem__ method for all keys. After deleting a key,
        getting and deleting the same key should raise a KeyError.
        """
        del fixed_input_map(key)
        with pytest.raises(KeyError):
            fixed_input_map(key)
        with pytest.raises(KeyError):
            del fixed_input_map(key)

    def test_empty(self, fixed_input_map):
        """After deleting all items, the map should be empty."""
        assert len(fixed_input_map) == 0


@pytest.mark.parametrize('map_pair', UNSORTED_MAPS, indirect=True)
class TestUnsortedMapRandomInput:
    """Test class for unsorted maps with large random inputs.
    We added a large number of random items to each map and assert that the length
    of the map and the set of items are correct, then we randomly remove 2/3 of
    the items and assert again. The process is repeated three times.
    """

    def test_first_setitem(self, map_pair):
        my_map, python_dict = random_setitem(*map_pair)
        assert len(my_map) == len(python_dict)
        assert set(my_map.items()) == set(python_dict.items())

    def test_first_delitem(self, map_pair):
        my_map, python_dict = random_delitem(*map_pair)
        assert len(my_map) == len(python_dict)
        assert set(my_map.items()) == set(python_dict.items())

    def test_second_setitem(self, map_pair):
        my_map, python_dict = random_setitem(*map_pair)
        assert len(my_map) == len(python_dict)
        assert set(my_map.items()) == set(python_dict.items())

    def test_second_delitem(self, map_pair):
        my_map, python_dict = random_delitem(*map_pair)
        assert len(my_map) == len(python_dict)
        assert set(my_map.items()) == set(python_dict.items())

    def test_third_setitem(self, map_pair):
        my_map, python_dict = random_setitem(*map_pair)
        assert len(my_map) == len(python_dict)
        assert set(my_map.items()) == set(python_dict.items())

    def test_third_delitem(self, map_pair):
        my_map, python_dict = random_delitem(*map_pair)
        assert len(my_map) == len(python_dict)
        assert set(my_map.items()) == set(python_dict.items())


@pytest.mark.parametrize('fixed_input_map', SORTED_MAPS, indirect=True)
class TestSortedMapFixedInput:
    """Test class for sorted maps with small fixed inputs."""

    def test_minimum(self, fixed_input_map):
        """Test the minimum method."""
        assert fixed_input_map.minimum() == SORTED_ITEMS(0)

    def test_maximum(self, fixed_input_map):
        """Test the maximum method."""
        assert fixed_input_map.maximum() == SORTED_ITEMS(-1)

    def test_no_predecessor(self, fixed_input_map):
        """Test the predecessor method for the smallest key,
        which results in a KeyError."""
        with pytest.raises(KeyError):
            fixed_input_map.predecessor(SORTED_KEYS(0))

    def test_no_successor(self, fixed_input_map):
        """Test the successor method for the largest key,
        which results in a KeyError."""
        with pytest.raises(KeyError):
            fixed_input_map.successor(SORTED_KEYS(-1))

    @pytest.mark.parametrize('key', SORTED_KEYS(1:))
    def test_predecessor(self, fixed_input_map, key):
        """Test the predecessor method for all but the smallest key."""
        prev_item = SORTED_ITEMS(SORTED_KEYS.index(key) - 1)
        assert fixed_input_map.predecessor(key) == prev_item

    @pytest.mark.parametrize('key', SORTED_KEYS(:-1))
    def test_successor(self, fixed_input_map, key):
        """Test the successor method for all but the largest key."""
        next_item = SORTED_ITEMS(SORTED_KEYS.index(key) + 1)
        assert fixed_input_map.successor(key) == next_item


@pytest.mark.parametrize('map_pair', SORTED_MAPS, indirect=True)
class TestSortedMapRandomInput:
    """Test class for sorted maps with large random inputs.
    Similar to TestUnsortedMapRandomInput, we randomly add and remove items
    three times, but we test whether the lists of keys are sorted instead.
    """

    def test_first_setitem(self, map_pair):
        my_map, python_dict = random_setitem(*map_pair)
        assert list(my_map) == sorted(python_dict)

    def test_first_delitem(self, map_pair):
        my_map, python_dict = random_delitem(*map_pair)
        assert list(my_map) == sorted(python_dict)

    def test_second_setitem(self, map_pair):
        my_map, python_dict = random_setitem(*map_pair)
        assert list(my_map) == sorted(python_dict)

    def test_second_delitem(self, map_pair):
        my_map, python_dict = random_delitem(*map_pair)
        assert list(my_map) == sorted(python_dict)

    def test_third_setitem(self, map_pair):
        my_map, python_dict = random_setitem(*map_pair)
        assert list(my_map) == sorted(python_dict)

    def test_third_delitem(self, map_pair):
        my_map, python_dict = random_delitem(*map_pair)
        assert list(my_map) == sorted(python_dict)

Questions:

  1. Is using @pytest.mark.parametrize to test different classes with similar interfaces a good idea?
  2. There are tests that depend on the results of previous tests, especially when it comes to deleting items and random inputs. Is this a bad practice?
  3. It is difficult to test __setitem__ separately since all other methods depend on it. How can I write a separate test case for __setitem__?
  4. Did I use too many global constants in the test script?
  5. What else can I improve my test code?