首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >TDD方法与简单解决方案

TDD方法与简单解决方案
EN

Code Review用户
提问于 2013-03-20 15:22:36
回答 1查看 374关注 0票数 2

您可以为下面的枚举类编写多少个测试。给定以下命令,我将查找以下输出:

代码语言:javascript
复制
java fileName HORIZON_BOX, HORIZON_BOX_WITH_CC, HORIZON_BOX_WITH_CC

1 HORIZON_BOX: 20.00
2 HORIZON_BOX_WITH_CC @ 30.00 : 60.00
GRAND TOTAL : 80.00

解决这个问题最好的解决方法是什么?

代码语言:javascript
复制
public enum Product {

    HORIZON_BOX(30.00),
    HORIZON_BOX_WITH_CC(50.00),
    HORIZON_BOX_WITH_CC_2_TB(100.00),
    HORIZON_MULTIROOM(75.00),
    HUB(20.00);

    private double price;

    private Product(double price) {
        this.price = price;
    }

    public double getPrice() {
        return price;
    }

}

我所作的测试如下:

代码语言:javascript
复制
public class ProductTest {

/**
 * Test that fails as we cannot access the private constructor of the Enum
 * Written before any code is written to test
 */
@Test
public void testProductNothingImplemented() {
    // Product("Nothing has been implemented yet");

}

/**
 * Test expectedvalue of 20
 */
@Test
public void testProductHORIZONBoxHUB() {

    assertEquals(20, Product.HUB.getPrice(), 0);

}

/**
 * Test expectedvalue of 50 for HORIZON_BOX_WITH_HD
 */
@Test
public void testProductHORIZON_BOX_WITH_HD() {

    assertEquals(50, Product.HORIZON_BOX_WITH_CC.getPrice(), 0);

}

/**
 * Test expectedvalue of 100 for HORIZON_BOX_WITH_HD_2_TB
 */
@Test
public void testProductHORIZON_BOX_WITH_HD_2_TB() {

    assertEquals(100, Product.HORIZON_BOX_WITH_CC_2_TB.getPrice(), 0);

}

/**
 * Test expectedvalue of 75 for HORIZON_MULTIROOM
 */
@Test
public void testProductHORIZON_MULTIROOM() {

    assertEquals(75, Product.HORIZON_MULTIROOM.getPrice(), 0);

}

/**
 * Test expectedvalue of 30 for HORIZON_BOX
 */
@Test
public void testProductHORIZON_BOX() {

    assertEquals(30, Product.HORIZON_BOX.getPrice(), 0);

}

/**
 * test method to compute total with zero products
 */
@Test
public void testComputeEmptyMap() {
    Map<String, Integer> testMap = new HashMap<String, Integer>();

    //setup map
    Horizon Horizon = new Horizon();
    assertEquals(new Double(0), Horizon.computeAndPrintTotal(testMap));
}

/**
 * test method to compute total with two elements but second element is ) products
 */
@Test
public void testComputeAndPrintTotalWithOneProductHavingZeroFrequency() {
    Map<String, Integer> testMap = new HashMap<String, Integer>();

    //setup map
    testMap.put("HUB", 1);
    testMap.put("HORIZON_BOX", 0);

    Horizon Horizon = new Horizon();
    assertEquals(new Double(20), Horizon.computeAndPrintTotal(testMap));
}


/**
 * test method to compute total with two products
 */
@Test
public void testComputeAndPrintTotalPass() {
    Map<String, Integer> testMap = new HashMap<String, Integer>();

    testMap.put("HUB", 1);
    testMap.put("HORIZON_BOX", 2);

    Horizon Horizon = new Horizon();
    assertEquals(new Double(80), Horizon.computeAndPrintTotal(testMap));
}




}

#######################################################################################

我拥有以下内容:执行的主类是

代码语言:javascript
复制
public class Horizon {

private Map<String, Integer> argFrequencyCount = new HashMap<String, Integer>();

double total = 0;

@SuppressWarnings("rawtypes")
public static void main(String[] args) {

    Horizon horizon = new Horizon();

    for (String productName : args) {

        Integer frequency = horizon.argFrequencyCount.get(productName);

        horizon.argFrequencyCount.put(productName, (frequency == null) ? 1
                : frequency + 1);

    }

    horizon.argFrequencyCount = horizon.sortProductMapByFrequency(horizon.argFrequencyCount);

    for (Iterator iterator = horizon.argFrequencyCount.entrySet().iterator(); iterator
            .hasNext();) {
        @SuppressWarnings("unchecked")
        Map.Entry<String, Integer> productCount = (Map.Entry<String, Integer>) iterator
                .next();
        horizon.outputPrintHelper(productCount.getKey(),
                productCount.getValue());

    }
    horizon.computeAndPrintTotal(horizon.argFrequencyCount);

}

/**
 * method to print total
 * 
 * @param argFrequencyCount
 */
public Double computeAndPrintTotal(Map<String, Integer> argFrequencyCount) {

    for (Iterator<Map.Entry<String, Integer>> iterator = argFrequencyCount.entrySet().iterator(); iterator
            .hasNext();) {
        Map.Entry<String, Integer> productCount = (Map.Entry<String, Integer>) iterator
                .next();

        total = total + productCount.getValue()
                * Product.valueOf(productCount.getKey()).getPrice();

    }
    System.out.println("GRAND TOTAL : £" + total);
    return total;

}

/**
 * Method to print the items and corresponding item total
 * 
 * @param prod
 * @param numberOfItems
 */

private void outputPrintHelper(String prod, int numberOfItems) {

    Product product = Product.valueOf(prod);

    switch (product) {
    case HUB:
        if (numberOfItems == 1) {
            System.out.println(numberOfItems + " HUB : £"
                    + Product.HUB.getPrice());

        } else {
            System.out.println(numberOfItems + " HUB @  £" + Product.HUB
                    + " : £" + numberOfItems * Product.HUB.getPrice());
        }
        break;
    case HORIZON_BOX:
        if (numberOfItems == 1) {
            System.out.println(numberOfItems + " HORIZON_BOX : £"
                    + Product.HORIZON_BOX.getPrice());

        } else {
            System.out.println(numberOfItems + " HORIZON_BOX @  £"
                    + Product.HORIZON_BOX.getPrice() + " : £" + numberOfItems
                    * Product.HORIZON_BOX.getPrice());
        }
        break;
    case HORIZON_BOX_WITH_CC:
        if (numberOfItems == 1) {
            System.out.println(numberOfItems + " HORIZON_BOX_WITH_CC : £"
                    + Product.HORIZON_BOX_WITH_CC.getPrice());

        } else {
            System.out.println(numberOfItems + " HORIZON_BOX_WITH_CC @  £"
                    + Product.HORIZON_BOX_WITH_CC.getPrice() + " : £"
                    + numberOfItems * Product.HORIZON_BOX_WITH_CC.getPrice());
        }

        break;
    case HORIZON_BOX_WITH_CC_2_TB:
        if (numberOfItems == 1) {
            System.out.println(numberOfItems + " HORIZON_BOX_WITH_CC_2_TB : £"
                    + Product.HORIZON_BOX_WITH_CC_2_TB.getPrice());

        } else {
            System.out.println(numberOfItems
                    + " HORIZON_BOX_WITH_CC_2_TB @  £"
                    + Product.HORIZON_BOX_WITH_CC_2_TB.getPrice() + " : £"
                    + numberOfItems
                    * Product.HORIZON_BOX_WITH_CC_2_TB.getPrice());
        }

        break;
    case HORIZON_MULTIROOM:
        if (numberOfItems == 1) {
            System.out.println(numberOfItems + " HORIZON_MULTIROOM : £"
                    + Product.HORIZON_MULTIROOM.getPrice());

        } else {
            System.out.println(numberOfItems + " HORIZON_MULTIROOM @  £"
                    + Product.HORIZON_MULTIROOM.getPrice() + " : £"
                    + numberOfItems * Product.HORIZON_MULTIROOM.getPrice());
        }
    }

}

/**
 * Sort the HashMap by number of items in descending order
 * 
 */
private Map<String, Integer> sortProductMapByFrequency(
        Map<String, Integer> passedMap) {

    List<String> mapKeys = new ArrayList<String>(passedMap.keySet());

    List<Integer> mapValues = new ArrayList<Integer>(passedMap.values());

    Collections.sort(mapValues);
    Collections.sort(mapKeys);

    LinkedHashMap<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();

    Iterator<Integer> valueIt = mapValues.iterator();
    while (valueIt.hasNext()) {
        Object val = valueIt.next();
        Iterator<String> keyIt = mapKeys.iterator();

        while (keyIt.hasNext()) {
            Object key = keyIt.next();
            String comp1 = passedMap.get(key).toString();
            String comp2 = val.toString();

            if (comp1.equals(comp2)) {
                passedMap.remove(key);
                mapKeys.remove(key);
                sortedMap.put((String) key, (Integer) val);
                break;
            }

        }

    }
    return sortedMap;

}

}
EN

回答 1

Code Review用户

发布于 2013-03-22 07:02:12

@David很好地回答了关于测试的问题,没有什么重要的补充。在第二个问题审查设计时,设计也有一些重要的问题,但我不想让以下几点落空:

  • 对于泛型来说,您似乎是新手:@SuppressWarnings(“rawtype”)如果您使用了Iterator<Map.Entry<String, Integer>>而不是原始的Iterator,那么您不仅可以避免这个警告,还可以避免未检查的强制转换(以及附带的警告)。
  • 当您在集合中迭代时,您应该更倾向于每种语法,除非您要在循环中添加或删除元素。比较: for (Iterator iterator = horizon.argFrequencyCount.entrySet() .iterator();iterator.hasNext();) {@SuppressWarnings(“未检查”) Map.Entry productCount = (Map.Entry) iterator.next();以下为: for (Map.Entry productCount : horizon.argFrequencyCount.entrySet()) {
  • 应该将各种Map<String, Integer>更改为Map<Product, Integer>;因为这些映射包含“每个产品的数量”。
  • 您在这里丢失了类型信息: Iterator valueIt = mapValues.iterator();Object val = valueIt.next();Iterator valueIt = mapValues.iterator();int val = valueIt.next();//您应该使用Integer = valueIt.next();//如果val可能为null,这里不需要--这里的每个循环也都有帮助。
  • 由于您丢失了上面的类型信息;您正在比较对象的字符串表示形式: string comp1 = passedMap.get(key).toString();String comp2 = val.toString();if (comp1.Eques(Comp2)){相反,您可以编写: if (passedMap.get(key).equals(val)) {
  • 这个片段的另一点是passedMapkeyval根本不是描述性的。现在比较一下: if (passedMap.get(key).equals(val)) {与: if .equals{哪个读得更好?名字很重要。
  • 这里是sortProductMapByFrequency的签名:私有Map sortProductMapByFrequency( Map passedMap) {返回值的契约应该从签名中明显看出。如果要对集合进行排序,则返回值应该有一定的顺序。因此,至少您应该显式地返回一个LinkedHashMap。如果要根据键对地图条目进行排序,则应该返回一个SortedMap。因为您根据值(而不仅仅是键)对条目进行排序,所以不能。如果您要对一个List<Map.Entry<X,Y>>的条目进行排序,那么我希望得到一个Map<X,Y>。你不能用SortedMap,straightforwardly,但是您可以使用排序的多个时间点,例如,如果您有ApacheCommons或Guava。这里有一个可维护性的权衡。
  • 另外,当您遍历一个映射并同时使用键和值时,您应该像在其他地方那样使用entrySet来迭代。这样,嵌套循环就可以是一个循环,效率更高、可读性更强。或者您可以这样做:私有List> sortProductMapByFrequency( Map productFrequencies) { List>条目=新ArrayList>(productFrequencies.entrySet());Collections.sort(条目,compareProductFrequencies();返回条目;} Comparator> compareProductFrequencies() {返回新的Comparator>() {@覆盖公共int比较( Entry lhs,Entry rhs) {返回lhs.getValue().compareTo(rhs.getValue());};}
票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/24161

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档