如何将main方法class转为Junit测试class?

How to turn main method class to Junit test class?

我在 Intellij IDEA 上写了一个名为 Sales Taxes 的小项目。对于 运行 程序,我包含了一个 main 方法。现在我需要为项目编写 JUnit 测试。我没有太多关于编写测试 classes 的经验。如何将我的主要方法转为 Junit 测试 class?

这是我构建的项目:

Basic sales tax is applicable at a rate of 10% on all goods, except books, food, and medical products that are exempt. Import duty is an additional sales tax applicable on all imported goods at a rate of 5%, with no exemptions. When I purchase items I receive a receipt which lists the name of all the items and their price (including tax), finishing with the total cost of the items, and the total amounts of sales taxes paid. The rounding rules for sales tax are that for a tax rate of n%, a shelf price of p contains (np/100 rounded up to the nearest 0.05) amount of sales tax. Write an application that prints out the receipt details for these shopping baskets...

Product.java

/*
Definition of Product.java class
Fundamental object for the project. 
It keeps all features of the product.
At description of the product, description of the input line for output line.
typeOfProduct: 0:other 1:food 2:book 3: medical products

*/

public class Product{

    private int typeOfProduct=0;
    private boolean imported=false;
    private double price=0;
    private double priceWithTaxes=0;
    private double taxes=0;
    private int quantity=0;
    private String description="";


    public Product(int quantity, int typeOfProduct, boolean imported, double price, String description)
    {
        this.quantity=quantity;
        this.typeOfProduct = typeOfProduct;
        this.imported = imported;
        this.price = price;
        this.description = description;

    }

    public void setTypeOfProduct(int typeOfProduct)
    {
        this.typeOfProduct = typeOfProduct;
    }

    public int getTypeOfProduct()
    {
        return typeOfProduct;
    }

    public void setImported(boolean imported)
    {
        this.imported = imported;
    }

    public boolean getImported()
    {
        return imported;
    }

    public void setPrice(double price)
    {
        this.price = price;
    }

    public double getPrice()
    {
        return price;
    }

    public void setTaxes(double taxes)
    {
        this.taxes = taxes;
    }

    public double getTaxes()
    {
        return taxes;
    }

    public void setPriceWithTaxes(double priceWithTaxes)
    {
        this.priceWithTaxes = priceWithTaxes;
    }

    public double getPriceWithTaxes()
    {
        return priceWithTaxes;
    }

    public void setQuantity(int quantity)
    {
        this.quantity = quantity;
    }

    public int getQuantity()
    {
        return quantity;
    }

    public void setDescription(String description)
    {
        this.description = description;
    }

    public String getDescription()
    {
        return description;
    }
}

TaxCalculator.java

/*
Definition of TaxCalculator.java class
At constructor a Product object is taken.
taxCalculate method; adds necessary taxes to price of product.
Tax rules: 
    1. if the product is imported, tax %5 of price
    2. if the product is not food, book or medical goods, tax %10 of  price
typeOfProduct: 0:food 1:book 2: medical products 3:other
*/
public class TaxCalculator {

private Product product=null;

    public TaxCalculator(Product product)
    {
        this.product=product;
    }

    public void taxCalculate()
    {
        double price=product.getPrice();
        double tax=0;

        //check impoted or not
        if(product.getImported())
        {
            tax+= price*5/100;

        }

        //check type of product
        if(product.getTypeOfProduct()==3)
        {
            tax+= price/10;
        }

        product.setTaxes(Util.roundDouble(tax));
        product.setPriceWithTaxes(Util.roundDouble(tax)+price);
    }
}

Util.java

import java.text.DecimalFormat;
/*
Definition of Util.java class
It rounds and formats the price and taxes.
Round rules for sales taxes: rounded up to the nearest 0.05
Format: 0.00
*/

public class Util {

    public static String round(double value)
    {
        double rounded = (double) Math.round(value * 100)/ 100;

        DecimalFormat df=new DecimalFormat("0.00");
        rounded = Double.valueOf(df.format(rounded));

        return df.format(rounded).toString();
    }

    public static double roundDouble(double value)
    {
        double rounded = (double) Math.round(value * 20)/ 20;

        if(rounded<value)
        {
            rounded = (double) Math.round((value+0.05) * 20)/ 20;
        }

        return rounded;
    }

    public static String roundTax(double value)
    {
        double rounded = (double) Math.round(value * 20)/ 20;

        if(rounded<value)
        {
            rounded = (double) Math.round((value+0.05) * 20)/ 20;
        }

        DecimalFormat df=new DecimalFormat("0.00");
        rounded = Double.valueOf(df.format(rounded));

        return df.format(rounded).toString();
    }
}

SalesManager.java

import java.util.ArrayList;
import java.util.StringTokenizer;
/*
Definition of SalesManager.java class
This class asks to taxes to TaxCalculator Class and creates Product    objects.
 */
public class SalesManager {

    private String [][] arTypeOfProduct = new String [][]{
            {"CHOCOLATE", "CHOCOLATES", "BREAD", "BREADS", "WATER", "COLA", "EGG", "EGGS"},
            {"BOOK", "BOOKS"},
            {"PILL", "PILLS", "SYRUP", "SYRUPS"}
    };
    /*
     * It takes all inputs as ArrayList, and returns output as ArrayList
     * Difference between output and input arrayLists are Total price and Sales Takes.
     */
    public ArrayList<String> inputs(ArrayList<String> items)
    {
        Product product=null;
        double salesTaxes=0;
        double total=0;

        TaxCalculator tax=null;

        ArrayList<String> output=new ArrayList<String>();

        for(int i=0; i<items.size(); i++)
        {
            product= parse(items.get(i));
            tax=new TaxCalculator(product);
            tax.taxCalculate();

            salesTaxes+=product.getTaxes();
            total+=product.getPriceWithTaxes();

            output.add(""+product.getDescription()+" "+Util.round(product.getPriceWithTaxes()));

        }

        output.add("Sales Taxes: "+Util.round(salesTaxes));

        output.add("Total: "+Util.round(total));

        return output;
    }

    /*
     * The method takes all line and create product object.
     * To create the object, it analyses all line.
     * "1 chocolate bar at 0.85"
     * First word is quantity
     * Last word is price
     * between those words, to analyse it checks all words
     */
    public Product parse(String line)
    {
        Product product=null;

        String productName="";
        int typeOfProduct=0;
        boolean imported=false;
        double price=0;
        int quantity=0;
        String description="";

        ArrayList<String> wordsOfInput = new ArrayList<String>();

        StringTokenizer st = new StringTokenizer(line, " ");

        String tmpWord="";
        while (st.hasMoreTokens())
        {
            tmpWord=st.nextToken();
            wordsOfInput.add(tmpWord);
        }

        quantity=Integer.parseInt(wordsOfInput.get(0));

        imported = searchImported(wordsOfInput);

        typeOfProduct = searchTypeOfProduct(wordsOfInput);

        price=Double.parseDouble(wordsOfInput.get(wordsOfInput.size()-1));

        description=wordsOfInput.get(0);
        for(int i=1; i<wordsOfInput.size()-2; i++)
        {
            description=description.concat(" ");
            description=description.concat(wordsOfInput.get(i));
        }
        description=description.concat(":");

        product=new Product(quantity, typeOfProduct, imported, price, description);

        return product;
    }

    /*
     * It checks all line to find "imported" word, and returns boolean as imported or not.
     */
    public boolean searchImported(ArrayList<String> wordsOfInput)
    {
        boolean result =false;
        for(int i=0; i<wordsOfInput.size(); i++)
        {
            if(wordsOfInput.get(i).equalsIgnoreCase("imported"))
            {
                return true;
            }
        }

        return result;
    }

    //typeOfProduct: 0:food 1:book 2: medical goods 3:other
    /*
     * It checks all 2D array to find the typeOf product
     * i=0 : Food
     * i=1 : Book 
     * i=2 : Medical goods
     */
    public int searchTypeOfProduct (ArrayList<String> line)
    {
        int result=3;
        for(int k=1; k<line.size()-2; k++)
        {
            for(int i=0; i<arTypeOfProduct.length; i++)
            {
                for(int j=0; j<arTypeOfProduct[i].length; j++)
                {
                    if(line.get(k).equalsIgnoreCase(arTypeOfProduct[i][j]))
                    {
                        return i;
                    }
                }
            }
        }
        return result;
    }
 }

SalesTaxes.java

import java.io.IOException;
import java.util.ArrayList;
public class SalesTaxes {

    public static void main(String args[]) throws IOException
    {
        ArrayList<String> input = new ArrayList<String>();
        ArrayList<String> output = new ArrayList<String>();

        SalesManager sal = new SalesManager();

            /*
             * First input set
             */
        System.out.println("First input Set");
        System.out.println();

        input = new ArrayList<String>();
        input.add("1 book at 12.49");
        input.add("1 music CD at 14.99");
        input.add("1 chocolate bar at 0.85");
        sal=new SalesManager();
        output= sal.inputs(input);

        for(int i=0; i<output.size(); i++)
        {
            System.out.println(output.get(i));
        }

            /*
             * Second input set
             */
        System.out.println();
        System.out.println("Second input Set");
        System.out.println();

        input = new ArrayList<String>();
        input.add("1 imported box of chocolates at 10.00");
        input.add("1 imported bottle of perfume at 47.50");
        sal=new SalesManager();
        output= sal.inputs(input);

        for(int i=0; i<output.size(); i++)
        {
            System.out.println(output.get(i));
        }
            /*
             * Third input set
             */
        System.out.println();
        System.out.println("Third input Set");
        System.out.println();

        input = new ArrayList<String>();
        input.add("1 imported bottle of perfume at 27.99");
        input.add("1 bottle of perfume at 18.99");
        input.add("1 packet of headache pills at 9.75");
        input.add("1 box of imported chocolates at 11.25");
        output= sal.inputs(input);

        for(int i=0; i<output.size(); i++)
        {
            System.out.println(output.get(i));
        }
    }
}

一个"unit test"是一个class。

所以我不会从 main 方法开始:那不会给你 "unit tests"。那会给你一个 "integration test"(同时测试一堆 classes)。

所以,对于单元测试,我会先写一个 UtilTest class 来测试你的 Util class。它有 public 方法,可以很容易地给出不同的输入和断言的结果。例如如果你给 roundTax 零或 21.0 等,你会得到什么?

我觉得你可以从搜索如何编写单元测试开始,也许你不会有这样的问题。重点是测试某些功能。例如,在您的情况下,您应该测试 taxCalculate 方法并检查您的产品中的税费设置是否正确,在这种情况下您可能需要一个产品 getter。

另外,检查一下:how to write a unit test