groovy,geb(selenium),spockによる自動化テスト その1
環境
jdk,mvn,groovy,geb,webdriver
webdriverダウンロード
https://github.com/mozilla/geckodriver/releases環境変数設定 PATH、JAVA_HOME、M2_HOME
バージョン確認
E:\dev>mvn -version
Apache Maven 3.3.3 (7994120775791599e205a5524ec3e0dfe41d4a06; 2015-04-22T20:57:37+09:00)
Maven home: E:\dev\apache-maven-3.3.3
Java version: 1.8.0_40, vendor: Oracle Corporation
Java home: D:\pleiades-e4.4\java\8\jre
Default locale: ja_JP, platform encoding: MS932
OS name: “windows 7”, version: “6.1”, arch: “amd64”, family: “dos”
E:\dev>groovy -version
Groovy Version: 2.4.8 JVM: 1.8.0_40 Vendor: Oracle Corporation OS: Windows 7
Groovy Shellでgebを実行する
groovysh
ライブラリダウンロード
groovy:000> import groovy.grape.Grape
===> groovy.grape.Grape
groovy:000> Grape.grab(group: ‘org.gebish’, module: ‘geb-core’, version:‘1.1.1’)
===> null
groovy:000> Grape.grab(group: ‘org.seleniumhq.selenium’, module: ‘selenium-firefox-driver’, version: ‘3.1.0’)
===> null
環境変数
groovy:000> System.setProperty(“webdriver.gecko.driver”, “E:\dev\geckodriver.exe”)
===> null
groovy:000> browser = new geb.Browser()
===> geb.Browser@6ad11a56
ブラウザオープン
groovy:000> browser.go ‘http://google.com’
URL:google.comが開かれる。
検索キー入力&検索ボタンクリック
groovy:000>form = browser.$(‘form#tsf’)
groovy:000>form.size()
groovy:000>form.q = ‘http://javait.hatenablog.com/’
groovy:000>btnK = form.find(‘input[name=btnK]’)
groovy:000>btnK.click()
検索結果タイトルを表示
groovy:000>browser.$(‘h3’).each { println it.text() }
liguofeng29’s blog
2016年現在のJavaについて - arclamp
arclamp
よねのはてな
Challenge Java EE
A Memorandum
HTML5のform関連 - 新規属性 - liguofeng29’s blog
【Java】GETメソッドでHTTP通信をする汎用オブジェクトを自作してみた …
google-http-java-client 入門 - ひだまりソケットは壊れない
略・・・・・
Groovy ScriptでGebを利用する
- スクリプト
@Grab('org.gebish:geb-core:1.1.1') @Grab('org.seleniumhq.selenium:selenium-firefox-driver:3.1.0') import geb.Browser System.setProperty("webdriver.gecko.driver", "E:\\dev\\groovy_geb\\geckodriver.exe") def keywords = args.join(' ') Browser.drive { go 'http://google.com' $('form#tsf').with { q = keywords btnK().click() } // argsがなければ // geb.waiting.WaitTimeoutException: condition did not pass in 5.0 seconds waitFor { $('h3').size() > 0 } $('h3').each { println "* ${it.text()}" } }.quit()
- 実行
groovy script1.groovy javait.hatenablog.com
Get Properties from File.
package org.lee.util; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Enumeration; import java.util.Iterator; import java.util.Properties; public class PropertyUtil { private Properties getProperties(String path) { Properties conf = new Properties(); InputStream inputStream = null; try { inputStream = new FileInputStream(new File(path)); conf.load(inputStream); } catch (IOException e) { e.printStackTrace(); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } return conf; } public static void main(String[] args) { PropertyUtil util = new PropertyUtil(); Properties p = util.getProperties("ppp.conf"); // 方法1 Enumeration<?> en = p.propertyNames(); while (en.hasMoreElements()) { String key = (String) en.nextElement(); System.out.println(key + "=" + p.get(key)); } // 方法2 Iterator<?> it = p.keySet().iterator(); while (it.hasNext()) { String key = (String)it.next(); System.out.println(key + "=" + p.get(key)); } } }
b=2 a=1 b=2 a=1
※うん・・順序は保持してくれないね。
junit.framework.TestSuiteを使って、AllTest.javaを実装する。
・AllTest.java
package org.lee.samle; import junit.framework.JUnit4TestAdapter; import junit.framework.Test; import junit.framework.TestSuite; public class AllTest { public static Test suite() { TestSuite suite = new TestSuite(); // TestCase継承した場合 suite.addTestSuite(AppTestWithTestCase.class); // TestCase継承してない場合 suite.addTest(new JUnit4TestAdapter(AppTestWithoutTestCase.class)); return suite; } }
・App.java(テスト対象)
package org.lee.samle; /** * Hello world! * */ public class App { public boolean isAdult(int age) { return age >= 20; } }
・AppTestWithoutTestCase.java(テストクラス)
package org.lee.samle; import org.junit.Test; import org.junit.internal.runners.JUnit4ClassRunner; import org.junit.runner.RunWith; import org.seasar.framework.unit.S2Assert; /** * Unit test for simple App. */ @RunWith(JUnit4ClassRunner.class) public class AppTestWithoutTestCase { App app; @Test public void testIsAdult() { app = new App(); S2Assert.assertFalse(app.isAdult(19)); S2Assert.assertTrue(app.isAdult(20)); S2Assert.assertTrue(app.isAdult(21)); } }
・AppTestWithTestCase .java(テストクラス)
package org.lee.samle; import junit.framework.TestCase; import org.seasar.framework.unit.S2Assert; /** * Unit test for simple App. */ public class AppTestWithTestCase extends TestCase{ App app; public void testIsAdult() { app = new App(); S2Assert.assertFalse(app.isAdult(19)); S2Assert.assertTrue(app.isAdult(20)); S2Assert.assertTrue(app.isAdult(21)); } }
※AllTest.javaを実行することで対象のすべてのテストクラスが実行される。 ※AllTest.javaをEclEmmaなどでカバレッジを確認すればよい。
Hibernate - 関連マッピング - @OneToMany
@OneToManyのサンプル
一人(1)が複数(N)のアドレスを持つ。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- ドライバ --> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <!-- 接続情報 --> <property name="connection.url">jdbc:mysql://localhost/hibernate</property> <property name="connection.username">root</property> <property name="connection.password">xxxx</property> <!-- 各種設定 --> <property name="hibernate.c3p0.max_size">20</property> <property name="hibernate.c3p0.min_size">1</property> <property name="hibernate.c3p0.timeout">5000</property> <!-- プール内最大Statement --> <property name="hibernate.c3p0.max_statements">100</property> <property name="hibernate.c3p0.idle_test_period">3000</property> <property name="hibernate.c3p0.acquire_increment">2</property> <property name="hibernate.c3p0.validate">true</property> <!-- DB方言解消 --> <property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property> <!-- 必要に応じて表生成 --> <property name="hbm2ddl.auto">update</property> <!-- 生成SQL表示 --> <property name="show_sql">true</property> <property name="hibernate.format_sql">true</property> <!-- マッピングテーブル --> <mapping class="relation.one_to_many.Person"/> <mapping class="relation.one_to_many.Address"/> </session-factory> </hibernate-configuration>
package relation.one_to_many; import java.util.HashSet; import java.util.Set; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.OneToMany; import javax.persistence.Table; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.CascadeType; @Entity @Table(name = "person_inf") public class Person { @Id @Column(name = "person_id") @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private String name; private int age; @OneToMany(targetEntity = Address.class) @JoinColumn(name = "person_id", referencedColumnName = "person_id") @Cascade(CascadeType.ALL) private Set<Address> addresses = new HashSet<>(); public void setId(Integer id) { this.id = id; } public Integer getId() { return this.id; } public void setName(String name) { this.name = name; } public String getName() { return this.name; } public void setAge(int age) { this.age = age; } public int getAge() { return this.age; } public void setAddresses(Set<Address> addresses) { this.addresses = addresses; } public Set<Address> getAddresses() { return this.addresses; } }
package relation.one_to_many; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "address_inf") public class Address { @Id @Column(name = "address_id") @GeneratedValue(strategy = GenerationType.IDENTITY) private int addressId; private String addressDetail; public Address() { } public Address(String addressDetail) { this.addressDetail = addressDetail; } public void setAddressId(int addressId) { this.addressId = addressId; } public int getAddressId() { return this.addressId; } public void setAddressDetail(String addressDetail) { this.addressDetail = addressDetail; } public String getAddressDetail() { return this.addressDetail; } }
package relation.one_to_many; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; public class HibernateUtil { public static final SessionFactory sessionFactory; static { try { Configuration cfg = new Configuration().configure(); ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder() .applySettings(cfg.getProperties()).build(); sessionFactory = cfg.buildSessionFactory(serviceRegistry); } catch (Throwable ex) { System.err.println("Initial SessionFactory creation failed." + ex); throw new ExceptionInInitializerError(ex); } } public static final ThreadLocal<Session> session = new ThreadLocal<Session>(); public static Session currentSession() throws HibernateException { Session s = session.get(); if (s == null) { s = sessionFactory.openSession(); session.set(s); } return s; } public static void closeSession() throws HibernateException { Session s = session.get(); if (s != null) s.close(); session.set(null); } }
package relation.one_to_many; import org.hibernate.Session; import org.hibernate.Transaction; public class PersonManager { public static void main(String[] args) { Session session = HibernateUtil.currentSession(); Transaction tx = session.beginTransaction(); // Person生成 Person p = new Person(); p.setName("佐藤"); p.setAge(21); // Address生成 Address address1 = new Address("住所1-1"); Address address2 = new Address("住所2-2"); // 関連 p.getAddresses().add(address1); p.getAddresses().add(address2); // 保存 session.persist(p); tx.commit(); HibernateUtil.closeSession(); } }
結果
ログ: Hibernate: insert into person_inf (age, name) values (?, ?) Hibernate: insert into address_inf (addressDetail) values (?) Hibernate: insert into address_inf (addressDetail) values (?) Hibernate: update address_inf set person_id=? where address_id=? Hibernate: update address_inf set person_id=? where address_id=? mysql> select * from person_inf; +-----------+-----+--------+ | person_id | age | name | +-----------+-----+--------+ | 2 | 21 | 佐藤 | +-----------+-----+--------+ 1 row in set (0.00 sec) mysql> select * from address_inf; +------------+---------------+-----------+ | address_id | addressDetail | person_id | +------------+---------------+-----------+ | 1 | 住所2-2 | 2 | | 2 | 住所1-1 | 2 | +------------+---------------+-----------+ 2 rows in set (0.00 sec)
Hibernate - 関連マッピング - @ManyToOne
@ManyToOneのサンプル
複数の人(N)が同じ(1)のアドレスを持つ。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- ドライバ --> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <!-- 接続情報 --> <property name="connection.url">jdbc:mysql://localhost/hibernate</property> <property name="connection.username">root</property> <property name="connection.password">xxxxx</property> <!-- 各種設定 --> <property name="hibernate.c3p0.max_size">20</property> <property name="hibernate.c3p0.min_size">1</property> <property name="hibernate.c3p0.timeout">5000</property> <!-- プール内最大Statement --> <property name="hibernate.c3p0.max_statements">100</property> <property name="hibernate.c3p0.idle_test_period">3000</property> <property name="hibernate.c3p0.acquire_increment">2</property> <property name="hibernate.c3p0.validate">true</property> <!-- DB方言解消 --> <property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property> <!-- 必要に応じて表生成 --> <property name="hbm2ddl.auto">update</property> <!-- 生成SQL表示 --> <property name="show_sql">true</property> <property name="hibernate.format_sql">true</property> <!-- マッピングテーブル --> <mapping class="relation.many_to_one.Person"/> <mapping class="relation.many_to_one.Address"/> </session-factory> </hibernate-configuration>
package relation.many_to_one; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.CascadeType; @Entity @Table(name = "person_inf") public class Person { @Id @Column(name = "person_id") @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private String name; private int age; @ManyToOne(targetEntity = Address.class) @JoinColumn(name = "address_id", nullable = false) @Cascade(CascadeType.ALL) private Address address; public void setId(Integer id) { this.id = id; } public Integer getId() { return this.id; } public void setName(String name) { this.name = name; } public String getName() { return this.name; } public void setAge(int age) { this.age = age; } public int getAge() { return this.age; } public void setAddress(Address address) { this.address = address; } public Address getAddress() { return this.address; } }
package relation.many_to_one; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "address_inf") public class Address { @Id @Column(name = "address_id") @GeneratedValue(strategy = GenerationType.IDENTITY) private int addressId; private String addressDetail; public Address() { } public Address(String addressDetail) { this.addressDetail = addressDetail; } public void setAddressId(int addressId) { this.addressId = addressId; } public int getAddressId() { return this.addressId; } public void setAddressDetail(String addressDetail) { this.addressDetail = addressDetail; } public String getAddressDetail() { return this.addressDetail; } }
package relation.many_to_one; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; public class HibernateUtil { public static final SessionFactory sessionFactory; static { try { Configuration cfg = new Configuration().configure(); ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder() .applySettings(cfg.getProperties()).build(); sessionFactory = cfg.buildSessionFactory(serviceRegistry); } catch (Throwable ex) { System.err.println("Initial SessionFactory creation failed." + ex); throw new ExceptionInInitializerError(ex); } } public static final ThreadLocal<Session> session = new ThreadLocal<Session>(); public static Session currentSession() throws HibernateException { Session s = session.get(); if (s == null) { s = sessionFactory.openSession(); session.set(s); } return s; } public static void closeSession() throws HibernateException { Session s = session.get(); if (s != null) s.close(); session.set(null); } }
package relation.many_to_one; import org.hibernate.Session; import org.hibernate.Transaction; public class PersonManager { public static void main(String[] args) { Session session = HibernateUtil.currentSession(); Transaction tx = session.beginTransaction(); // Person生成 Person p = new Person(); p.setName("佐藤"); p.setAge(20); // Address生成 Address address1 = new Address("住所1-1"); // 関連 p.setAddress(address1); // p保存 session.persist(p); Address address2 = new Address("住所2-2"); p.setAddress(address2); tx.commit(); HibernateUtil.closeSession(); } }
結果
ログ: Hibernate: insert into address_inf (addressDetail) values (?) Hibernate: insert into person_inf (address_id, age, name) values (?, ?, ?) Hibernate: insert into address_inf (addressDetail) values (?) Hibernate: update person_inf set address_id=?, age=?, name=? where person_id=? mysql> select * from person_inf; +-----------+-----+--------+------------+ | person_id | age | name | address_id | +-----------+-----+--------+------------+ | 1 | 20 | 佐藤 | 2 | +-----------+-----+--------+------------+ 1 row in set (0.00 sec) mysql> select * from address_inf; +------------+---------------+ | address_id | addressDetail | +------------+---------------+ | 1 | 住所1-1 | | 2 | 住所2-2 | +------------+---------------+ 2 rows in set (0.00 sec)