5

I want to do plain UI testing (i.e., not using SWTBot or other UI test frameworks) of NatTable contents.

My approach is to create a shell, add my custom NatTable and then access the cell and check its contents (data value, config label etc.):

// Note: this is Xtend code
@Before
def void setup()
{
    shell = new Shell(Display.getCurrent)
    shell.layout = new FillLayout
    parent = new Composite(shell, SWT.NONE)
    parent.layout = new GridLayout
    fixture = new MyNatTableViewer(parent) // this is my custom nattable impl under test
    shell.pack
    shell.visible = true
}

@Test
def void testLabel() 
{ 
    assertCellLabel(2, 2, "test-label");
}

def assertCellLabel(int row, int col, String expected)
{
    val labels = parameterTable.getCellByPosition(col, row)?.configLabels
    assertThat(labels).describedAs("Labels for row " + row + " col " + col).isNotNull
    assertThat(labels.labels).describedAs("Labels for row " + row + " col " + col).contains(expected)
}

To test my other components it was enough to just create the shell and the parent composite; packing and setting visible was not required for my tests to work. Yet, with NatTable, getCellByPosition() returns null if the cell is not visible - so I added the code to pack and set the shell visible. This works for small tables (with 2 rows and a few columns).

Sadly, it does not work for large tables. I suspect this is because the viewport layer does not create cells which are not in the visible area (which is, I know, the strength of NatTable - that it only creates the required structures on demand). This is, of course, desired for normal runtime behavior.

But is there a(nother) way to get the cell in a guaranteed way (in other words, can I make the NatTable/ViewportLayer believe that the cell is visible so I don't get null as long as the cell exists content-wise?)

I could, of course, test my label accumulators, data providers etc. directly, but I wanted to approach this more from a black-box point of view here.

Stefan Winkler
  • 3,871
  • 1
  • 18
  • 35
  • I don't have an answer to your question, but the usual advice is to keep the top-most View/UI layer as thin and dumb as possible and test everything else. In your case it would indeed mean to test your individual NatTable components (Accumulators, Providers, Event Handlers), and trust NatTable to display it correctly. – jhyot Apr 28 '16 at 07:07

2 Answers2

1

That question is contradictory in itself. You are asking for a black box approach for testing NatTable, but you want to change the behavior of NatTable on testing. That is not a black box approach!

If you really want to test with a black box approach, you need to ensure that the cell is rendered. This can be done by triggering scrolling, e.g. by executing the ShowCellInViewportCommand. That is the real black box approach, because returning null for a non-visible cell is the correct result.

If you need something in between a real black box approach and an approach that makes use of internal knowledge (which you are asking for) you have to ways to get there.

  1. Operate on a layer below the ViewportLayer. Typically the SelectionLayer can be used. But of course this doesn't need to mean anything, because the layer stack can differ from setup to setup. The ViewportLayer is the one that introduces the virtual nature to a NatTable and the scrolling ability. It avoids the access to the underlying layers. So asking one of these will return the value you expect.

  2. Disable the ViewportLayer by executing the TurnViewportOffCommand. This is basically a hack and could trigger additional things in the back that you might not want. But I have seen that suggestion in other contexts and therefore want to name it here. I don't suggest to use it anyway!

Note that both approaches are more like hacks when we are talking about black box testing, because you are making assumptions to the composition. They can not be applied in general because of the various configuration abilities.

Regarding the hidden question about why you need to set the Shell visible. Well basically because the SWT events for painting and resizing need to be triggered in order to start the size calculations and printing of NatTable correctly according to the Shell state. In our examples (which are also plain SWT) we call Shell#open().

And as a last comment on your implementation, I don't understand why you are sub-classing NatTable. Our API was never intended to do that. I suppose you do this to do some static pre-configuration e.g. the layer stack. But personally I don't like that approach. Everytime someone extends our classes to override some internal methods it ends up in questions or bug reports because the behavior changes. But I think that is generally an issue of an open API to give developers the most possible flexibility on customization.

Dirk Fauth
  • 4,128
  • 2
  • 13
  • 23
  • Thanks, Dirk, for your detailed answer. You are correct, my approach is not actually black-box, I just wanted access the model from the top, more or less... Regarding your last remark: I am not subclassing `NatTable`; this detail has just been blurred when condensing my code for posting. I use a class I call `AbstractNatTableViewer` which wraps a `NatTable` and provides the layer and config setup which is common for multiple `NatTables` in our applications, so we have like a reusable base implementation for `NatTable`s and their common code... – Stefan Winkler Apr 28 '16 at 07:39
1

I am also trying to read data from invisible cells of nattable. I am trying to use ShowCellInViewportCommand as follows:

widget.doCommand(new ShowCellInViewportCommand(gridlayer.getBodyLayer(), column, row)); 
//where row is say 50 and column is 20 and the cell is invisible.

I also tried,

widget.doCommand(new ShowRowInViewportCommand(widget.getLayer(), row)); 
//here the default value given by nattable.getLayer is passed

widget corrosponds to nattable instance.

After the call, nothing happens in UI. The cell does not get displayed. Do I need to do anything else?

How should I go to read invisible cells of nattable.

cb0
  • 8,415
  • 9
  • 52
  • 80
Apurv
  • 15
  • 3
  • I would also like to see this as a new question. I also can't answer a question with the given information. How does your layer stack look like? How many rows do you have and which row do you try to make visible? The `ShowCellInViewportCommand` is handled by the `ShowCellInViewportCommandHandler` which is registered to the `ViewportLayer`. If that is all in place, it should work. If you try to make a row visible that doesn't exist (mind the index-position transformation) nothing will happen. – Dirk Fauth Jun 23 '16 at 14:08