sql >> Databáze >  >> NoSQL >> HBase

Jak na to:Testování aplikací HBase pomocí oblíbených nástrojů

Zatímco přijetí Apache HBase pro vytváření aplikací pro koncové uživatele raketově vzrostlo, mnoho z těchto aplikací (a mnoho aplikací obecně) nebylo dobře otestováno. V tomto příspěvku se dozvíte některé ze způsobů, jak lze toto testování snadno provést.

Začneme testováním jednotek prostřednictvím JUnit, poté přejdeme k používání Mockito a Apache MRUnit a poté k použití miniklastru HBase pro testování integrace. (Samotná kódová základna HBase je testována prostřednictvím mini-klastru, tak proč ji nevyužít i pro upstream aplikace?)

Jako základ pro diskusi předpokládejme, že máte objekt přístupu k datům HBase (DAO), který provádí následující vložení do HBase. Logika by samozřejmě mohla být složitější, ale pro příklad to funguje.

public class MyHBaseDAO { public static void insertRecord(tabulka HTableInterface, HBaseTestObj obj) vyvolá výjimku { Put put =createPut(obj); table.put(put); } private static Put createPut(HBaseTestObj obj) { Put put =new Put(Bytes.toBytes(obj.getRowKey())); put.add(Bytes.toBytes("CF"), Bytes.toBytes("CQ-1"), Bytes.toBytes(obj.getData1())); put.add(Bytes.toBytes("CF"), Bytes.toBytes("CQ-2"), Bytes.toBytes(obj.getData2())); návrat vložit; }}

HBaseTestObj je základní datový objekt s gettry a settery pro rowkey, data1 a data2.

InsertRecord provede vložení do tabulky HBase proti rodině sloupců CF s CQ-1 a CQ-2 jako kvalifikátory. Metoda createPut jednoduše naplní Put a vrátí jej do volající metody.

Pomocí JUnit

JUnit, který je v tuto chvíli většině vývojářů v Javě dobře znám, lze snadno aplikovat na mnoho aplikací HBase. Nejprve přidejte závislost do svého pomu:

 junit   junit   4.11   test

Nyní v testovací třídě:

public class TestMyHbaseDAOData { @Test public void testCreatePut() vyvolá výjimku { HBaseTestObj obj =new HBaseTestObj(); obj.setRowKey("ROWKEY-1"); obj.setData1("DATA-1"); obj.setData2("DATA-2"); Put put =MyHBaseDAO.createPut(obj); asseEquals(obj.getRowKey(), Bytes.toString(put.getRow())); asseEquals(obj.getData1(), Bytes.toString(put.get(Bytes.toBytes("CF"), Bytes.toBytes("CQ-1")).get(0).getValue())); asseEquals(obj.getData2(), Bytes.toString(put.get(Bytes.toBytes("CF"), Bytes.toBytes("CQ-2")).get(0).getValue())); } }

Zde jste zajistili, že vaše metoda createPut vytvoří, naplní a vrátí objekt Put s očekávanými hodnotami.

Používání Mockito

Jak tedy postupovat při testování jednotek výše uvedenou metodou insertRecord? Jedním z velmi účinných přístupů je tak učinit pomocí Mockito.

Nejprve přidejte Mockito jako závislost do vašeho pomu:

   org.mockito   mockito-all   1.9.5 test 

Poté v testovací třídě:

@RunWith(MockitoJUnitRunner.class)veřejná třída TestMyHBaseDAO{  @Mock   soukromá tabulka HTableInterface; @Mock  private HTablePool hTablePool; @Captor  private ArgumentCaptor putCaptor; @Test  public void testInsertRecord() vyvolá výjimku {    //vrátí falešnou tabulku, když se getTable nazývá    when(hTablePool.getTable("tablename")).thenReturn(table); //vytvoří testovací objekt a provede volání DAO, které potřebuje testování    HBaseTestObj obj =new HBaseTestObj(); obj.setRowKey("ROWKEY-1"); obj.setData1("DATA-1"); obj.setData2("DATA-2"); MyHBaseDAO.insertRecord(tabulka, obj); ověřit(tabulka).put(putCaptor.capture()); Put put =putCaptor.getValue(); asseEquals(Bytes.toString(put.getRow()), obj.getRowKey()); ask(put.has(Bytes.toBytes("CF"), Bytes.toBytes("CQ-1"))); ask(put.has(Bytes.toBytes("CF"), Bytes.toBytes("CQ-2"))); asseEquals(Bytes.toString(put.get(Bytes.toBytes("CF"),Bytes.toBytes("CQ-1")).get(0).getValue()), "DATA-1"); asseEquals(Bytes.toString(put.get(Bytes.toBytes("CF"),Bytes.toBytes("CQ-2")).get(0).getValue()), "DATA-2"); }}

Zde jste naplnili HBaseTestObj hodnotami „ROWKEY-1“, „DATA-1“, „DATA-2“. Potom jste použili zesměšněnou tabulku a DAO k vložení záznamu. Zachytili jste Put, které by DAO vložilo, a ověřili, že klíč řádku, data1 a data2 jsou takové, jaké očekáváte.

Klíčem je zde správa fondu htable a vytváření instancí htable mimo DAO. To vám umožňuje zesměšňovat je čistě a testovat Puts, jak je uvedeno výše. Podobně se nyní můžete rozšířit do všech ostatních operací, jako je Získat, Skenovat, Smazat atd.

Použití MRUnit

S pravidelným testováním jednotek přístupu k datům se vraťme k úlohám MapReduce, které jdou proti tabulkám HBase.

Testování úloh MR, které jdou proti HBase, je stejně jednoduché jako testování běžných úloh MapReduce. MRUnit opravdu usnadňuje testování úloh MapReduce včetně těch HBase.

Představte si, že máte úlohu MR, která zapisuje do tabulky HBase „MyTest“, která má jednu rodinu sloupců, „CF“. Reduktor takové úlohy by mohl vypadat takto:

public class MyReducer extends TableReducer { public static final byte[] CF ="CF".getBytes(); public static final byte[] QUALIFIER ="CQ-1".getBytes(); public void reduction(Text key, Iterable values, Context context) vyvolá IOException, InterruptedException { //hromada zpracování pro extrakci dat, která mají být vložena, v našem případě řekněme, že jednoduše //připojujeme všechny záznamy, které obdržíme z mapovače pro tento konkrétní //klíč a vložte jeden záznam do dat HBase StringBuffer =new StringBuffer(); Put put =new Put(Bytes.toBytes(key.toString())); for (Textová hodnota:hodnoty) { data =data.append(val); } put.add(CF, QUALIFIER, Bytes.toBytes(data.toString())); //zápis do HBase context.write(new ImmutableBytesWritable(Bytes.toBytes(key.toString())), put); } }

Jak nyní postupujete při testování jednotky výše uvedeného reduktoru v MRUnit? Nejprve přidejte MRUnit jako závislost do vašeho pomu.

 org.apache.mrunit mrunit 1.0.0  test 

Poté v rámci testovací třídy použijte ReduceDriver, který poskytuje MRUnit, jak je uvedeno níže:

public class MyReducerTest {    ReduceDriver reductionDriver; byte[] CF ="CF".getBytes(); byte[] QUALIFIER ="CQ-1".getBytes(); @Before    public void setUp() {      Reduktor MyReducer =new MyReducer(); redukovatDriver =ReduceDriver.newReduceDriver(reducer); }     @Test   public void testHBaseInsert() vyvolá IOException {      String strKey ="RowKey-1", strValue ="DATA", strValue1 ="DATA1", strValue2 ="DATA2"; Seznam seznam =new ArrayList(); list.add(new Text(strValue)); list.add(new Text(strValue1)); list.add(new Text(strValue2)); //protože v našem případě vše, co reduktor dělá, je připojení záznamů, které mapovač         //odešle, měli bychom získat zpět následující      String expectOutput =strValue + strValue1 + strValue2; //Nastavení vstupu, napodobení toho, co by mapper předal      //do reduktoru a spusťte test      reductionDriver.withInput(new Text(strKey), seznam); //spusťte redukci a získáte její výstup      List> result =reductionDriver.run(); //extrahuje klíč z výsledku a ověří     asservals(Bytes.toString(result.get(0).getFirst().get()), strKey); //extrahuje hodnotu pro CF/QUALIFIER a ověří      Vložte a =(Put)result.get(0).getSecond(); String c =Bytes.toString(a.get(CF, QUALIFIER).get(0).getValue()); claimEquals(expectedOutput,c ); }}

V podstatě jste si po spoustě zpracování v MyReducer ověřili, že:

  • Výstup je takový, jaký očekáváte.
  • Položka Put, která je vložena do HBase, má jako klíč řádku „RowKey-1“.
  • „DATADATA1DATA2“ je hodnota pro rodinu sloupců CF a kvalifikátor sloupců CQ.

Můžete také testovat mapovače, které získávají data z HBase podobným způsobem pomocí MapperDriver, nebo testovat úlohy MR, které čtou z HBase, zpracovávají data a zapisují do HDFS.

Použití miniklastru HBase

Nyní se podíváme na to, jak postupovat při testování integrace. HBase se dodává s HBaseTestingUtility, díky kterému je psaní integračního testování s miniklastrem HBase přímočaré. Aby bylo možné stáhnout správné knihovny, jsou ve vašem pomu vyžadovány následující závislosti:

   org.apache.hadoop   hadoop-common   2.0.0-cdh4.2.0   test-jar   test org.apache.hbase   hbase   0.94.2-cdh4.2.0   test-jar   test         org.apache.hadoop   hadoop-hdfs   2.0.0-cdh4.2.0   test-jar   test   org.apache.hadoop   hadoop-hdfs   2.0.0-cdh4.2.0   test

Nyní se podívejme, jak provést integrační test pro vložku MyDAO popsaný v úvodu:

veřejná třída MyHBaseIntegrationTest {soukromý statický nástroj HBaseTestingUtility;byte[] CF ="CF".getBytes();byte[] QUALIFIER ="CQ-1".getBytes();@Beforepublic void setup() vyvolá výjimku { nástroj =new HBaseTestingUtility(); utility.startMiniCluster();}@Test public void testInsert() vyvolá výjimku { HTableInterface table =utility.createTable(Bytes.toBytes("MyTest"), Bytes.toBytes("CF")); HBaseTestObj obj =new HBaseTestObj(); obj.setRowKey("ROWKEY-1"); obj.setData1("DATA-1"); obj.setData2("DATA-2"); MyHBaseDAO.insertRecord(tabulka, obj); Get get1 =new Get(Bytes.toBytes(obj.getRowKey())); get1.addColumn(CF, CQ1); Výsledek výsledek1 =tabulka.get(get1); asseEquals(Bytes.toString(result1.getRow()), obj.getRowKey()); asseEquals(Bytes.toString(result1.value()), obj.getData1()); Get get2 =new Get(Bytes.toBytes(obj.getRowKey())); get2.addColumn(CF, CQ2); Výsledek výsledek2 =table.get(get2); asseEquals(Bytes.toString(result2.getRow()), obj.getRowKey()); asseEquals(Bytes.toString(result2.value()), obj.getData2()); }}

Zde jste vytvořili mini-klastr HBase a spustili jej. Poté jste vytvořili tabulku nazvanou „MyTest“ s jednou rodinou sloupců, „CF“. Vložili jste záznam pomocí DAO, který jste potřebovali otestovat, provedli jste Get ze stejné tabulky a ověřili jste, že DAO vložil záznamy správně.

Totéž lze udělat pro mnohem komplikovanější případy použití spolu s úlohami MR, jako jsou ty, které jsou uvedeny výše. Můžete také přistupovat k miniklastrům HDFS a ZooKeeper vytvořeným při vytváření HBase, spustit úlohu MR, odeslat ji do HBase a ověřit vložené záznamy.

Jen krátké upozornění:spuštění miniklastru trvá 20 až 30 sekund a nelze jej provést ve Windows bez Cygwin. Protože by však měly být spouštěny pouze pravidelně, delší doba běhu by měla být přijatelná.

Ukázkový kód pro výše uvedené příklady najdete na https://github.com/sitaula/HBaseTest. Šťastné testování!


  1. Mongoose:CastError:Odeslání do ObjectId selhalo pro hodnotu [object Object] na cestě _id

  2. Operátor agregace MongoDB $sortByCount

  3. mongodb, repliky a chyba:{ $err :not master and slaveOk=false, kód:13435 }

  4. mangoose jedinečný:pravda, nefunguje