2013-09-22 40 views
-2

所以我有一個運行的代碼,但我需要編寫測試類(細胞)中的一個,我不知道如何去這個問題。測試在Java中(Junit4)一類

通常情況下,我會在CellsTest的開始,這將封裝構造函數調用,這依賴於實現整體方案之類的具體類名有一個輔助類。這個輔助類將返回該程序的一個實例。

所以,我倒是覺得是,我需要有類似:

private Maze createMaze() { 
      return new Maze(); 
     } 

但後來,我的測試方法不能訪問細胞的方法,只是迷宮方法...所以我猜測,這是錯誤的,我不知道我應該如何實際上可以這樣做。

//Maze.java 
    package falstad; 
    import java.awt.*; 
    import java.util.ArrayList; 
    import java.util.Iterator; 

    /** 
    * Class handles the user interaction for the maze. 
    */ 
    //public class Maze extends Panel { 
    public class Maze { 
      final private ArrayList<Viewer> views = new ArrayList<Viewer>() ; 
      MazePanel panel ; // graphics to draw on, shared by all views 
      private int state;      
      private int percentdone = 0; 
      private boolean showMaze; 
      private boolean showSolution; 
      private boolean solving; 
      private boolean mapMode; 
      //static final int viewz = 50;  
      int viewx, viewy, angle; 
      int dx, dy; 
      int px, py ; 
      int walkStep; 
      int viewdx, viewdy; 
      boolean deepdebug = false; 
      boolean allVisible = false; 
      boolean newGame = false; 

      int mazew; // width 
      int mazeh; // height 
      Cells mazecells ; 
      Distance mazedists ; 
      Cells seencells ; 

      BSPNode rootnode ; 

      // Mazebuilder is used to calculate a new maze together with a solution 
      // The maze is computed in a separate thread. It is started in the local Build method. 
      MazeBuilder mazebuilder; 

      final int ESCAPE = 27; 
      int method = 0 ; // 0 : default method, Falstad's original code 

      int zscale = Constants.VIEW_HEIGHT/2; 

      private RangeSet rset; 

      //Constructor 
      public Maze() { 
        super() ; 
        panel = new MazePanel() ; 
      } 
      //selects a generation method 
      public Maze(int method) 
      { 
        super() ; 
        if (1 == method) 
          this.method = 1 ; 
        panel = new MazePanel() ; 
      } 

      public void init() { 
        state = Constants.STATE_TITLE; 
        rset = new RangeSet(); 
        panel.initBufferImage() ; 
        addView(new MazeView(this)) ; 
        notifyViewerRedraw() ; 
      } 

      // Method obtains a new Mazebuilder and computes new maze 
      private void build(int skill) { 
        state = Constants.STATE_GENERATING; 
        percentdone = 0; 
        notifyViewerRedraw() ; 
        // select generation method 
        switch(method){ 
        case 1 : mazebuilder = new MazeBuilderPrim(); 
        break ; 
        case 0: 
        default : mazebuilder = new MazeBuilder(); 
        break ; 
        } 
        mazew = Constants.SKILL_X[skill]; 
        mazeh = Constants.SKILL_Y[skill]; 
        mazebuilder.build(this, mazew, mazeh, Constants.SKILL_ROOMS[skill], Constants.SKILL_PARTCT[skill]); 
      } 

      //Call back method for MazeBuilder to communicate newly generated maze 
      public void newMaze(BSPNode root, Cells c, Distance dists, int startx, int starty) { 
        if (Cells.deepdebugWall) 
        { 
          c.saveLogFile(Cells.deepedebugWallFileName); 
        } 
        showMaze = showSolution = solving = false; 
        mazecells = c ; 
        mazedists = dists; 
        seencells = new Cells(mazew+1,mazeh+1) ; 
        rootnode = root ; 
        setCurrentDirection(1, 0) ; 
        setCurrentPosition(startx,starty) ; 
        walkStep = 0; 
        viewdx = dx<<16; 
        viewdy = dy<<16; 
        angle = 0; 
        mapMode = false; 
        state = Constants.STATE_PLAY; 
        cleanViews() ; 
        addView(new FirstPersonDrawer(Constants.VIEW_WIDTH,Constants.VIEW_HEIGHT, 
            Constants.MAP_UNIT,Constants.STEP_SIZE, mazecells, seencells, 10, mazedists.getDists(), mazew, mazeh, root, this)) ; 

        addView(new MapDrawer(Constants.VIEW_WIDTH,Constants.VIEW_HEIGHT,Constants.MAP_UNIT,Constants.STEP_SIZE, mazecells, seencells, 10, mazedists.getDists(), mazew, mazeh, this)) ; 

        notifyViewerRedraw() ; 
      } 



      public void addView(Viewer view) { 
        views.add(view) ; 
      } 
      public void removeView(Viewer view) { 
        views.remove(view) ; 
      } 
      private void cleanViews() { 

        Iterator<Viewer> it = views.iterator() ; 
        while (it.hasNext()) 
        { 
          Viewer v = it.next() ; 
          if ((v instanceof FirstPersonDrawer)||(v instanceof MapDrawer)) 
          { 
            //System.out.println("Removing " + v); 
            it.remove() ; 
          } 
        } 

      } 
      private void notifyViewerRedraw() { 

        Iterator<Viewer> it = views.iterator() ; 
        while (it.hasNext()) 
        { 
          Viewer v = it.next() ; 

          v.redraw(panel.getBufferGraphics(), state, px, py, viewdx, viewdy, walkStep, Constants.VIEW_OFFSET, rset, angle) ; 
        } 

        panel.update() ; 
      } 
      private void notifyViewerIncrementMapScale() { 

        Iterator<Viewer> it = views.iterator() ; 
        while (it.hasNext()) 
        { 
          Viewer v = it.next() ; 
          v.incrementMapScale() ; 
        } 

        panel.update() ; 
      } 
      private void notifyViewerDecrementMapScale() { 

        Iterator<Viewer> it = views.iterator() ; 
        while (it.hasNext()) 
        { 
          Viewer v = it.next() ; 
          v.decrementMapScale() ; 
        } 

        panel.update() ; 
      } 
      boolean isInMapMode() { 
        return mapMode ; 
      } 
      boolean isInShowMazeMode() { 
        return showMaze ; 
      } 
      boolean isInShowSolutionMode() { 
        return showSolution ; 
      } 
      public String getPercentDone(){ 
        return String.valueOf(percentdone) ; 
      } 
      public Panel getPanel() { 
        return panel ; 
      } 
      private void setCurrentPosition(int x, int y) 
      { 
        px = x ; 
        py = y ; 
      } 
      private void setCurrentDirection(int x, int y) 
      { 
        dx = x ; 
        dy = y ; 
      } 
      void buildInterrupted() { 
        state = Constants.STATE_TITLE; 
        notifyViewerRedraw() ; 
        mazebuilder = null; 
      } 
      final double radify(int x) { 
        return x*Math.PI/180; 
      } 
      public boolean increasePercentage(int pc) { 
        if (percentdone < pc && pc < 100) { 
          percentdone = pc; 
          if (state == Constants.STATE_GENERATING) 
          { 
            notifyViewerRedraw() ; 
          } 
          else 
            dbg("Warning: Receiving update request for increasePercentage while not in generating state, skip redraw.") ; 
          return true ; 
        } 
        return false ; 
      } 

      private void dbg(String str) { 
        //System.out.println(str); 
      } 

      private void logPosition() { 
        if (!deepdebug) 
          return; 
        dbg("x="+viewx/Constants.MAP_UNIT+" ("+ 
            viewx+") y="+viewy/Constants.MAP_UNIT+" ("+viewy+") ang="+ 
            angle+" dx="+dx+" dy="+dy+" "+viewdx+" "+viewdy); 
      } 
      private boolean checkMove(int dir) { 
        int a = angle/90; 
        if (dir == -1) 
          a = (a+2) & 3; 
        return mazecells.hasMaskedBitsFalse(px, py, Constants.MASKS[a]) ; 
      }   
      private void rotateStep() { 
        angle = (angle+1800) % 360; 
        viewdx = (int) (Math.cos(radify(angle))*(1<<16)); 
        viewdy = (int) (Math.sin(radify(angle))*(1<<16)); 
        moveStep(); 
      } 
      private void moveStep() { 
        notifyViewerRedraw() ; 
        try { 
          Thread.currentThread().sleep(25); 
        } catch (Exception e) { } 
      } 

      private void rotateFinish() { 
        setCurrentDirection((int) Math.cos(radify(angle)), (int) Math.sin(radify(angle))) ; 
        logPosition(); 
      } 

      private void walkFinish(int dir) { 
        setCurrentPosition(px + dir*dx, py + dir*dy) ; 

        if (isEndPosition(px,py)) { 
          state = Constants.STATE_FINISH; 
          notifyViewerRedraw() ; 
        } 
        walkStep = 0; 
        logPosition(); 
      } 

      private boolean isEndPosition(int x, int y) { 
        return x < 0 || y < 0 || x >= mazew || y >= mazeh; 
      } 

      synchronized private void walk(int dir) { 
        if (!checkMove(dir)) 
          return; 
        for (int step = 0; step != 4; step++) { 
          walkStep += dir; 
          moveStep(); 
        } 
        walkFinish(dir); 
      } 

      synchronized private void rotate(int dir) { 
        final int originalAngle = angle; 
        final int steps = 4; 

        for (int i = 0; i != steps; i++) { 
          angle = originalAngle + dir*(90*(i+1))/steps; 
          rotateStep(); 
        } 
        rotateFinish(); 
      } 
      //CLASS CONTROLLING PLAYER MOVEMENTS, REMOVED FOR CHARACTER COUNT 
      } 
    } 


//Cells.java 


package falstad; 

import java.io.BufferedWriter; 
import java.io.FileWriter; 

//This class encapsulates all access to a grid of cells 
public class Cells { 

    private int width; 
    private int height ; 
    private int[][] cells; 


    public Cells(int w, int h) { 
      width = w ; 
      height = h ; 
      cells = new int[w][h]; 
    } 


    public Cells(int[][] target){ 
      this(target.length, target[0].length); 
      for (int i=0; i<width; i++) 
        for (int j=0; j<height; j++) 
          this.cells[i][j]=target[i][j]; 
    } 

    public int getCells(int x, int y) 
    { 
      return cells[x][y] ; 
    } 
    static public int[] getMasks() { 
      return Constants.MASKS ; 
    } 

    public boolean canGo(int x, int y, int dx, int dy) { 
      if (hasMaskedBitsTrue(x, y, (getBit(dx, dy) << Constants.CW_BOUND_SHIFT))) 
        return false; 
      return isFirstVisit(x+dx, y+dy); 
    } 
    private int getBit(int dx, int dy) { 
      int bit = 0; 
      switch (dx + dy * 2) { 
      case 1: bit = Constants.CW_RIGHT; break; 
      case -1: bit = Constants.CW_LEFT; break; 
      case 2: bit = Constants.CW_BOT; break; 
      case -2: bit = Constants.CW_TOP; break; 
      default: dbg("getBit problem "+dx+" "+dy); break; 
      } 
      return bit; 
    } 
//CLASSES FOR BITWISE ADJUSTMENTS, REMOVED FOR CHARACTER COUNT 



    public void initialize() { 
      int x, y; 

      for (x = 0; x != width; x++) { 
        for (y = 0; y != height; y++) { 
          setBitToOne(x, y, (Constants.CW_VISITED | Constants.CW_ALL)); 
        } 
        setBitToOne(x, 0, Constants.CW_TOP_BOUND); 
        setBitToOne(x, height-1, Constants.CW_BOT_BOUND); 
      } 
      for (y = 0; y != height; y++) { 
        setBitToOne(0, y, Constants.CW_LEFT_BOUND); 
        setBitToOne(width-1, y, Constants.CW_RIGHT_BOUND); 
      } 
    } 

    public boolean areaOverlapsWithRoom(int rx, int ry, int rxl, int ryl) { 
      int x, y; 
      for (x = rx-1; x <= rxl+1; x++) 
      { 
        for (y = ry-1; y <= ryl+1; y++) 
        { 
          if (isInRoom(x, y)) 
            return true ; 
        } 
      } 
      return false ; 
    } 

    private void deleteBound(int x, int y, int dx, int dy) { 
      setBoundToZero(x, y, dx, dy); 
      setBoundToZero(x+dx, y+dy, -dx, -dy) ; 
    } 


    public void addBoundWall(int x, int y, int dx, int dy) { 

      setBoundAndWallToOne(x, y, dx, dy); 
      setBoundAndWallToOne(x+dx, y+dy, -dx, -dy); 
    } 

    public void deleteWall(int x, int y, int dx, int dy) { 
      setWallToZero(x, y, dx, dy); 
      setWallToZero(x+dx, y+dy, -dx, -dy); 

      if (deepdebugWall) 
        logWall(x, y, dx, dy); 

    public void markAreaAsRoom(int rw, int rh, int rx, int ry, int rxl, int ryl) { 
      int x; 
      int y; 
      for (x = rx; x <= rxl; x++) 
        for (y = ry; y <= ryl; y++) { 
          setAllToZero(x, y); 
          setInRoomToOne(x, y); 
        } 
      for (x = rx; x <= rxl; x++) { 
        addBoundWall(x, ry, 0, -1); 
        addBoundWall(x, ryl, 0, 1); 
      } 
      for (y = ry; y <= ryl; y++) { 
        addBoundWall(rx, y, -1, 0); 
        addBoundWall(rxl, y, 1, 0); 
      } 
      int wallct = (rw+rh)*2; 
      SingleRandom random = SingleRandom.getRandom() ; 
      for (int ct = 0; ct != 5; ct++) { 
        int door = random.nextIntWithinInterval(0, wallct-1); 
        int dx, dy; 
        if (door < rw*2) { 
          y = (door < rw) ? 0 : rh-1; 
          dy = (door < rw) ? -1 : 1; 
          x = door % rw; 
          dx = 0; 
        } else { 
          door -= rw*2; 
          x = (door < rh) ? 0 : rw-1; 
          dx = (door < rh) ? -1 : 1; 
          y = door % rh; 
          dy = 0; 
        } 
        deleteBound(x+rx, y+ry, dx, dy); 
      } 
    } 
    public boolean hasMaskedBitsTrue(int x, int y, int bitmask) { 
      return (cells[x][y] & bitmask) != 0; 
    } 

    public boolean isInRoom(int x, int y) { 
      return hasMaskedBitsTrue(x, y, Constants.CW_IN_ROOM); 
    } 
    private boolean isFirstVisit(int x, int y) { 
      return hasMaskedBitsTrue(x, y, Constants.CW_VISITED); 
    } 
    public boolean hasWallOnRight(int x, int y) { 
      return hasMaskedBitsTrue(x, y, Constants.CW_RIGHT); 
    } 
    public boolean hasWallOnLeft(int x, int y) { 
      return hasMaskedBitsTrue(x, y, Constants.CW_LEFT); 
    } 
    public boolean hasWallOnTop(int x, int y) { 
      return hasMaskedBitsTrue(x, y, Constants.CW_TOP); 
    } 
    public boolean hasWallOnBottom(int x, int y) { 
      return hasMaskedBitsTrue(x, y, Constants.CW_BOT); 
    } 

    public boolean hasNoWallOnBottom(int x, int y) { 
      return !hasMaskedBitsTrue(x, y, Constants.CW_BOT); 
    } 
    public boolean hasNoWallOnTop(int x, int y) { 
      return !hasMaskedBitsTrue(x, y, Constants.CW_TOP); 
    } 
    public boolean hasNoWallOnLeft(int x, int y) { 
      return !hasMaskedBitsTrue(x, y, Constants.CW_LEFT); 
    } 
    public boolean hasNoWallOnRight(int x, int y) { 
      return !hasMaskedBitsTrue(x, y, Constants.CW_RIGHT); 
    } 


    public boolean hasMaskedBitsFalse(int x, int y, int bitmask) { 
      return (cells[x][y] & bitmask) == 0; 
    } 

    public boolean hasMaskedBitsGTZero(int x, int y, int bitmask) { 
      return (cells[x][y] & bitmask) > 0; 
    } 


    private void dbg(String str) { 
      System.out.println("Cells: "+str); 
    } 

    public String toString() { 
      String s = "" ; 
      for (int i = 0 ; i < width ; i++) 
      { 
        for (int j = 0 ; j < height ; j++) 
          s += " i:" + i + " j:" + j + "=" + cells[i][j] ; 
        s += "\n" ; 
      } 
      return s ; 
    } 

    static boolean deepdebugWall = false; 
    static final String deepedebugWallFileName = "logDeletedWalls.txt" ; 
    StringBuffer traceWall = (deepdebugWall) ? new StringBuffer("x y dx dy\n") : null ; 


    private void logWall(int x, int y, int dx, int dy) { 
      if (null != traceWall) 
      { 
        traceWall.append(x + " " + y + " " + dx + " " + dy + "\n"); 
      } 
    } 

    public void saveLogFile(String filename) 
    { 
      try { 
        BufferedWriter out = new BufferedWriter(new FileWriter(filename)); 
      out.write(traceWall.toString()); 
      out.close(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    } 

} 

//MazeBuilder.java 


package falstad; 

public class MazeBuilder implements Runnable { 
     protected int width, height ; 
     Maze maze; 
     private int rooms; 
     int expectedPartiters; 
     protected int startx, starty ; 
     protected Cells cells; 
     protected Distance dists ; 
     protected SingleRandom random ; 
     Thread buildThread; 
     public MazeBuilder(){ 
      random = SingleRandom.getRandom(); 
    } 

    public MazeBuilder(boolean deterministic){ 
      if (true == deterministic) 
      { 
        System.out.println("Project 2: functionality to make maze generation deterministic not implemented yet! Fix this!"); 


      } 
      random = SingleRandom.getRandom(); 
    } 


    static int getSign(int num) { 
      return (num < 0) ? -1 : (num > 0) ? 1 : 0; 
    } 


    protected void generate() { 
      generatePathways(); 
      final int[] remote = dists.computeDistances(cells) ; 
      final int[] pos = dists.getStartPosition(); 
      startx = pos[0] ; 
      starty = pos[1] ; 
      setExitPosition(remote[0], remote[1]); 
    } 


    protected void generatePathways() { 
      int[][] origdirs = new int[width][height] ; 
      int x = random.nextIntWithinInterval(0, width-1) ; 
      int y = 0; 
      final int firstx = x ; 
      final int firsty = y ; 
      int dir = 0;    
      int origdir = dir;  
      cells.setVisitedFlagToZero(x, y); 
      while (true) {   
        int dx = Constants.DIRS_X[dir]; 
        int dy = Constants.DIRS_Y[dir]; 

        if (!cells.canGo(x, y, dx, dy)) { 

          dir = (dir+1) & 3; 
          if (origdir == dir) { 

            if (x == firstx && y == firsty) 
              break; 


            int odr = origdirs[x][y]; 
            dx = Constants.DIRS_X[odr]; 
            dy = Constants.DIRS_Y[odr]; 

            x -= dx; 
            y -= dy; 
            origdir = dir = random.nextIntWithinInterval(0, 3); 
          } 
        } else { 
          cells.deleteWall(x, y, dx, dy); 
          x += dx; 
          y += dy; 
          cells.setVisitedFlagToZero(x, y); 
          origdirs[x][y] = dir; 
          origdir = dir = random.nextIntWithinInterval(0, 3); 
        } 
      } 
    } 

    protected void setExitPosition(int remotex, int remotey) { 
      int bit = 0; 
      if (remotex == 0) 
        bit = Constants.CW_LEFT; 
      else if (remotex == width-1) 
        bit = Constants.CW_RIGHT; 
      else if (remotey == 0) 
        bit = Constants.CW_TOP; 
      else if (remotey == height-1) 
        bit = Constants.CW_BOT; 
      else 
        dbg("Generate 1"); 
      cells.setBitToZero(remotex, remotey, bit); 
      //System.out.println("exit position set to zero: " + remotex + " " + remotey + " " + bit + ":" + cells.hasMaskedBitsFalse(remotex, remotey, bit) 
      //    + ", Corner case: " + ((0 == remotex && 0 == remotey) || (0 == remotex && height-1 == remotey) || (width-1 == remotex && 0 == remotey) || (width-1 == remotex && height-1 == remotey))); 
    } 


    static final int MIN_ROOM_DIMENSION = 3 ; 
    static final int MAX_ROOM_DIMENSION = 8 ; 

    private boolean placeRoom() { 
      final int rw = random.nextIntWithinInterval(MIN_ROOM_DIMENSION, MAX_ROOM_DIMENSION); 
      if (rw >= width-4) 
        return false; 

      final int rh = random.nextIntWithinInterval(MIN_ROOM_DIMENSION, MAX_ROOM_DIMENSION); 
      if (rh >= height-4) 
        return false; 

      final int rx = random.nextIntWithinInterval(1, width-rw-1); 
      final int ry = random.nextIntWithinInterval(1, height-rh-1); 
      final int rxl = rx+rw-1; 
      final int ryl = ry+rh-1; 
      if (cells.areaOverlapsWithRoom(rx, ry, rxl, ryl)) 
        return false ; 
      cells.markAreaAsRoom(rw, rh, rx, ry, rxl, ryl); 
      return true; 
    } 

    static void dbg(String str) { 
      System.out.println("MazeBuilder: "+str); 
    } 



    public void build(Maze mz, int w, int h, int roomct, int pc) { 
      init(mz, w, h, roomct, pc); 
      buildThread = new Thread(this); 
      buildThread.start(); 
    } 
    private void init(Maze mz, int w, int h, int roomct, int pc) { 
      maze = mz; 
      width = w; 
      height = h; 
      rooms = roomct; 
      expectedPartiters = pc; 
      cells = new Cells(w,h) ; 
      dists = new Distance(w,h) ; 
      //colchange = random.nextIntWithinInterval(0, 255); 
    } 

    static final long SLEEP_INTERVAL = 100 ; 
      try { 
        cells.initialize(); 
        // rooms into maze 
        generateRooms(); 

        Thread.sleep(SLEEP_INTERVAL) ; 

        // pathways into the maze, 
        generate(); 

        Thread.sleep(SLEEP_INTERVAL) ; 

        final int colchange = random.nextIntWithinInterval(0, 255); 
        final BSPBuilder b = new BSPBuilder(maze, dists, cells, width, height, colchange, expectedPartiters) ; 
        BSPNode root = b.generateBSPNodes(); 

        Thread.sleep(SLEEP_INTERVAL) ; 

        // dbg("partiters = "+partiters); 
        maze.newMaze(root, cells, dists, startx, starty); 
      } 
      catch (InterruptedException ex) { 
        // dbg("Catching signal to stop") ; 
      } 
    } 

    static final int MAX_TRIES = 250 ; 


    private int generateRooms() { 
      int tries = 0 ; 
      int result = 0 ; 
      while (tries < MAX_TRIES && result <= rooms) { 
        if (placeRoom()) 
          result++ ; 
        else 
          tries++ ; 
      } 
      return result ; 
    } 

    public void interrupt() { 
      buildThread.interrupt() ; 
    } 
} 

很顯然,我不是要求別人寫一個測試,我 - 沒有任何的你,因爲這是相當明顯的家庭作業 - 但我想一些幫助在此起步。因此,如果任何人都能夠將我誤解爲我錯過的肯定顯而易見的伎倆,那就太棒了!

+1

-1用於鏈接到外部內容 –

+0

對不起!修復!試圖讓每個人都更容易閱讀,並且忘記了這個規則...... – user2309856

回答

1

Cells類單元測試可以大致如下: 當你單元測試Cells類,你可能不需要Cells類的MazeMazeBuilder,你只需要一個實例,並調用它的方法,以檢查他們的工作與其他應用程序正確隔離。

也看看這個:Unit testing in Java - what is it?,因爲它提供了一個很好的參考。

import org.junit.Assert; 
import org.junit.Test; 

public class CellsTest { 

    @Test 
    void testHasWallOnRight() { 
     //setup 
     int[][] target = new int[][] { { 0, 0, 0, 0 }, 
       { 0, 0, 0, 0 }, 
       { 0, 0, 0, 0 }, 
       { 0, 0, 0, 0 } }; 

     Cells a = new Cells(target); 

     //act 
     boolean result = a.hasWallOnRight(1,1); 

     //assert 
     Assert.assertFalse(result); 
    } 
} 
+0

哦,事後看來這很明顯!不勝感激 :) – user2309856