python单一测试在任何运行中获得不同的结果

时间:2016-04-21 10:05:36

标签: python unit-testing

我需要将SQL的结果转换为分层的dict。我创建类DictMaker并编写单个测试。但是测试的运行在某些时候失败或成功。我不明白这种行为。在课堂上没有随机的电话。

import unittest


class DictMaker:
    def __init__( self, input_ ):
        self._input = input_
        self._dict = { }

    def dict( self ):
        self._make( )
        return self._dict

    def _make( self ):
        for item in self._input:
            for long_key, val in item.items( ):
                self._add_leaf_value( long_key, val )

    def _add_leaf_value( self, long_key, val ):
        last = self._get_last_item( long_key )
        leaf = self._get_leaf_key( long_key )
        if leaf in last:
            if last[ leaf ] != val:
                list_ = self._get_last_list( long_key )
                key = self._get_leaf_key( long_key )
                list_.append( { key: val } )
        else:
            last[ leaf ] = val

    def _get_leaf_key( self, long_key ):
        return long_key.split( '.' )[ -1 ]

    def _get_last_item( self, long_key ):
        keys = long_key.split( '.' )[ :-1 ]
        parent_dict = self._dict
        parent_list = None
        for key in keys:
            if key in parent_dict:
                parent_list = parent_dict[ key ]
                parent_dict = parent_list[ -1 ]
            else:
                sub_dict = { }
                parent_list = [ sub_dict ]
                parent_dict[ key ] = parent_list
                parent_dict = sub_dict

        return parent_list[ -1 ]

    def _get_last_list( self, long_key ):
        keys = long_key.split( '.' )[ :-1 ]
        parent_dict = self._dict
        parent_list = None
        for key in keys:
            if key in parent_dict:
                parent_list = parent_dict[ key ]
                parent_dict = parent_list[ -1 ]
            else:
                sub_dict = { }
                parent_list = [ sub_dict ]
                parent_dict[ key ] = parent_list
                parent_dict = sub_dict

        return parent_list


class MyTestCase( unittest.TestCase ):
  def test_run( self ):
    input_ = [
        {
            'categories.id': 1,
            'categories.label': 'Computers',
            'categories.groups.id': 18,
            'categories.groups.label': 'Servers and Servers equipment',
            'categories.groups.names.id': 48,
            'categories.groups.names.label': 'HP Memory'
        },
        {
            'categories.id': 1,
            'categories.label': 'Computers',
            'categories.groups.id': 18,
            'categories.groups.label': 'Servers and Servers equipment',
            'categories.groups.names.id': 73,
            'categories.groups.names.label': 'HP Options for servers'
        },
        {
            'categories.id': 1,
            'categories.label': 'Computers',
            'categories.groups.id': 84,
            'categories.groups.label': 'Tablets',
            'categories.groups.names.id': 310,
            'categories.groups.names.label': 'Tablets Samsung'
        },
        {
            'categories.id': 1,
            'categories.label': 'Computers',
            'categories.groups.id': 84,
            'categories.groups.label': 'Tablets',
            'categories.groups.names.id': 313,
            'categories.groups.names.label': 'Tablets Sony'
        },
        {
            'categories.id': 2,
            'categories.label': 'Periphery',
            'categories.groups.id': 55,
            'categories.groups.label': 'Loundspeakers',
            'categories.groups.names.id': 330,
            'categories.groups.names.label': 'Loundspeakers Ritmix'
        },
        {
            'categories.id': 2,
            'categories.label': 'Periphery',
            'categories.groups.id': 55,
            'categories.groups.label': 'Loundspeakers',
            'categories.groups.names.id': 402,
            'categories.groups.names.label': 'Loundspeakers MICROLAB'
        },
        {
            'categories.id': 2,
            'categories.label': 'Periphery',
            'categories.groups.id': 58,
            'categories.groups.label': 'Keyboards, mouses',
            'categories.groups.names.id': 25,
            'categories.groups.names.label': 'mouses G-Cube'
        },
        {
            'categories.id': 2,
            'categories.label': 'Periphery',
            'categories.groups.id': 58,
            'categories.groups.label': 'Keyboards, mouses',
            'categories.groups.names.id': 27,
            'categories.groups.names.label': 'Keyboards BTC '
        },
    ]
    expected = {
        'categories': [
            {
                'id': 1,
                'label': 'Computers',
                'groups': [
                    {
                        'id': 18,
                        'label': 'Servers and Servers equipment',
                        'names': [
                            {
                                'id': 48,
                                'label': 'HP Memory'
                            },
                            {
                                'id': 73,
                                'label': 'HP Options for servers'
                            }
                        ]
                    },
                    {
                        'id': 84,
                        'label': 'Tablets',
                        'names': [
                            {
                                'id': 310,
                                'label': 'Tablets Samsung'
                            },
                            {
                                'id': 313,
                                'label': 'Tablets Sony'
                            }
                        ]
                    }
                ]
            },
            {
                'id': 2,
                'label': 'Periphery',
                'groups': [
                    {
                        'id': 55,
                        'label': 'Loundspeakers',
                        'names': [
                            {
                                'id': 330,
                                'label': 'Loundspeakers Ritmix'
                            },
                            {
                                'id': 402,
                                'label': 'Loundspeakers MICROLAB'
                            }
                        ]
                    },
                    {
                        'id': 58,
                        'label': 'Keyboards, mouses',
                        'names': [
                            {
                                'id': 25,
                                'label': 'mouses G-Cube'
                            },
                            {
                                'id': 27,
                                'label': 'Keyboards BTC '
                            }
                        ]
                    }
                ]
            }
        ]
    }

  maker = DictMaker( input_ )
  actual = maker.dict( )

  self.assertEqual( actual, expected )


if __name__ == '__main__':
    unittest.main( )

在网上它工作正常(可能是由于Pypy)。但是本地运行很奇怪。 python(3.4.3)

1 个答案:

答案 0 :(得分:0)

FIX。这是由于dict键在迭代时未定义。 解决问题添加力排序。

def _make( self ):
    for item in self._input:
        for long_key, val in item.items( ):
            self._add_leaf_value( long_key, val )

更改为

def _make( self ):
    for item in self._input:
        items = list( item.items( ) )
        items.sort( key=lambda t: len( t[ 0 ] ) )
        for long_key, val in items:
            self._add_leaf_value( long_key, val )