Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.RU > Java > Junit тестирование


Автор: Сергей737 28.06.17, 18:01
Разбираюсь с Junit в Eclipse. Eсть LRU и LFU алгоритмы с вложенными классами. Вот LRU класс:

<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    package Main;
    import java.util.LinkedHashMap;
    import java.util.Map;
     
     
     
    public class LRUAlgoritm<K, V> implements Cache<K, V>{
         private LRUStorage storage;
     
     
            public LRUAlgoritm(int capacity) {
                this.storage = new LRUStorage(capacity);
            }
     
        @Override
        public V get(K key) {
     
            return storage.get(key);
        }
        @Override
        public V put(K key, V value) {
     
            return storage.put(key,value);
        }
     
     
        private class LRUStorage extends LinkedHashMap<K, V>{
            private final int capacity;
     
            private LRUStorage (int capacity){
                this.capacity = capacity;
            }
            @Override
                protected boolean removeEldestEntry(Map.Entry<K, V> eldest){
                    return size()>capacity ;
                }
            }
     
        @Override
        public String toString() {
            return  "storage= " + storage ;
        }
     
     
    }

Вот LFU класс:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    package Main;
    import java.util.LinkedHashMap;
    import java.util.Map;
    import java.util.Objects;
     
    public class LFUCache<K, V> implements Cache<K, V> {
     
        private final LinkedHashMap<K, Node> storage; //the declaration of the variable "storage" for storing data with key type "K" and value type "Node".
        private final int capacity;
     
        public LFUCache(int capacity) {
            if (capacity <= 0) {//validation of the capacity on the negative and the zero value
                throw new IllegalArgumentException("Capacity should be more than 0");
            }
            this.capacity = capacity;
            this.storage = new LinkedHashMap<>(capacity, 1); //initialization of variable "storage" - data storage.
                                                                //Inside the parentheses: the specified initial capacity and load factor = 1
        }
    //overriding methods "get" and "put" to be implemented from the interface "Cache"
        @Override
        public V get(K key) {
            Node node = storage.get(key);//the get method of LinkedHashMap class according to the
                                            //"http://docs.oracle.com/javase/7/docs/api/java/util/LinkedHashMap.html"
                                            //returns "null" if the requested key is missing or
                                            //has the value - a Hash mapping key if the key exists in the cache storage "storage"
            if (node == null) {//check the value of the variable "node" to NULL
                return null;
            }
            return node.incrementFrequency().getValue();//if the value of the variable "node" is not NULL,
                                                        //then the called method to increase the frequency on the unit and
                                                        //obtain take associated with the key "key" variable value "value"
        }
     
        @Override
        public V put(K key, V value) {
           //   if (storage.get(key)!=null&& Objects.equals(value, storage.get(key).getValue()))
            //{return storage.get(key).incrementFrequency().getValue();}//verification of the presence of the led element in the cache storage "storage"
                                                                    //if the element is present then return the value from the cache store
     
            doEvictionIfNeeded(key);//verification of occupancy of the cache storage, and the presence of the inserted key in the cache storage "storage"
     
            Node oldNode = storage.put(key, new Node(value));//the put method, inherited from Map interface, returns the previous value associated with key,
                                                                //or null if there was no mapping for key
            if (oldNode == null) {
                return null;
            }
            return oldNode.getValue();
        }
     
     
    // method to displace the old value with the least frequency when the storage of the cached data is completely filled
        private void doEvictionIfNeeded(K putKey) {
            if (storage.size() < capacity) {//verification of occupancy of the cache storage
                return;
            }
            long minFrequency = Long.MAX_VALUE;//the maximum assignable value for a variable of type Long
            K keyToRemove = null;
            for (Map.Entry<K, Node> entry : storage.entrySet()) {//search cash store the minimum value of frequency the "frequency" of all those elements
                if (Objects.equals(entry.getKey(), putKey)) {
                    //no eviction required cause element already exists, we just need to replace it
                    return;
                }
                if (minFrequency >= entry.getValue().getFrequency()) {
                    minFrequency = entry.getValue().getFrequency();
                    keyToRemove = entry.getKey();
                }
            }
            storage.remove(keyToRemove);//removal item's key with the minimum number of calls
        }
    //an inner class "Node" in the object which is stored the value "value".
        //And is created for this value a variable to hold the frequency "frequency" to the value "value'
        private class Node {
            private final V value;
            private long frequency;
     
            //create a constructor with a parameter (a value of type V) to write the value in the node object.
            //And setting the initial value of the frequency of reference to "value" - "frequency" = 1
            public Node(V value) {
                this.value = value;
                this.frequency = 1;
            }
     
            public V getValue() {
                return value;
            }
     
            public long getFrequency() {
                return frequency;
            }
     
            public Node incrementFrequency() {// method to increase frequency by one(+1)
                ++frequency;
                return this;
            }
     
            @Override
            public String toString() {
                return "Node [value=" + value + ", frequency=" + frequency + "]";
            }
     
        }
        @Override
        public String toString() {
            return "storage = "+ storage + ", capacity=" + capacity ;
        }
    }

Для LRU алгоритма я сделал тест класс для класса LRUStorage IDE сгенерировала код класса с одним единственным методом:

<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    package Test;
     
    import static org.junit.Assert.*;
     
    import org.junit.Test;
     
    public class TestLRUAlgoritm {
     
        @Test
        public final void testRemoveEldestEntryEntryOfKV() {
            fail("Not yet implemented");
        }
     
    }


Каким образом его теперь протестировать? метод removeEldestEntry() это переопределенный метод LinkedHashMap ? какие значения ему отдавать, что бы они адекватны для тестирования? Пересмотрел и Ткача, Немчинского и Владыкина на простых примерах какие данные передать и какой ассерт взять понятно(добавляем 2 и 2 и ждем 4), здесь же голову сломал, кучу статей перечитал ничего не понимаю, помогите разобраться?

я только пытаюсь разобраться, что нужно теститровать и какую именно функциональность необходимо тестировать. В моем примере (class LRUAlgoritm) есть три метода во внешнем классе LRUAlgoritm (get, put, toString) и один во внутреннем классе LRUStorage (remove Eldest Entry). Все они переопределенные. Нужно ли тестировать их логику? Ведь по правилам нужно покрывать тестами 100% кода? Если да, то какие параметры и что на выходе тогда должно быть?

второй класс дан как разъяснение других примеров, для наглядности.

Powered by Invision Power Board (https://www.invisionboard.com)
© Invision Power Services (https://www.invisionpower.com)