File file = new File("phantom,.exe_file"); System.setProperty("phantomjs.binary.path", file.getAbsolutePath()); new DesiredCapabilities(); DesiredCapabilities desiredCapabilities = DesiredCapabilities.phantomjs(); desiredCapabilities.setJavascriptEnabled(true); // turn off logging ArrayList<String> cliArgsCap = new ArrayList<String>(); cliArgsCap.add("--webdriver-loglevel=NONE"); desiredCapabilities.setCapability(PhantomJSDriverService.PHANTOMJS_CLI_ARGS, cliArgsCap); Logger.getLogger(PhantomJSDriverService.class.getName()).setLevel(Level.OFF); driver = new PhantomJSDriver(desiredCapabilities);
Wednesday, April 27, 2016
Phantom JS
Implement phantomJS with logger OFF
Tuesday, April 26, 2016
Monday, April 25, 2016
A complete implementation of Junit Suite
This is the class under Test
This is test class for Addition
This is test class for Substraction
This is test class for Division
This is where the suite is implemented. All test classes are clubbed together
This is the runner class for suite
HHH
package com.junit.suite.example; public class Math { public static int addition(int num1, int num2) { return num1 + num2; } public static int substraction(int num1, int num2) { return num1 - num2; } public static double division(int num1, int num2) { return num1 / num2; } }
This is test class for Addition
package com.junit.suite.example; import static org.junit.Assert.*; import java.util.Arrays; import java.util.List; import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; // perform the test using parameters @RunWith(Parameterized.class) public class AdditionMathTest { int expectedNumber; int num1; int num2; // create a constructor to pass the values public AdditionMathTest(int expectedNumber, int num1, int num2) { // TODO Auto-generated constructor stub this.expectedNumber = expectedNumber; this.num1 = num1; this.num2 = num2; } // create a parameterized method @Parameters public static List<Object[]> createData() { return Arrays.asList(new Object[][] { {4,2,1}, {6,3,3}, {8,4,4} }); } @BeforeClass public static void setUpBeforeClass() throws Exception { } @AfterClass public static void tearDownAfterClass() throws Exception { } @Before public void setUp() throws Exception { } @After public void tearDown() throws Exception { } @Test public void testAddition1() { // System.out.println(expectedNumber+"\t"+num1+"\t"+num2); Assert.assertTrue(expectedNumber==(Math.addition(num1, num2))); } @Test public void testAddition2() { Assert.assertEquals(expectedNumber, Math.addition(num1, num2)); } }
This is test class for Substraction
package com.junit.suite.example; import static org.junit.Assert.*; import java.util.Arrays; import java.util.List; import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; @RunWith(Parameterized.class) public class SubstractionMathTest { int expectedNumber; int num1; int num2; // create a constructor to pass the values public SubstractionMathTest(int expectedNumber, int num1, int num2) { // TODO Auto-generated constructor stub this.expectedNumber = expectedNumber; this.num1 = num1; this.num2 = num2; } // create a parameterized method @Parameters public static List<Object[]> createData() { return Arrays.asList(new Object[][] { { 4, 2, 1 }, { 6, 3, 3 }, { 8, 4, 4 } }); } @BeforeClass public static void setUpBeforeClass() throws Exception { } @AfterClass public static void tearDownAfterClass() throws Exception { } @Before public void setUp() throws Exception { } @After public void tearDown() throws Exception { } @Test public void testAddition() { // System.out.println(expectedNumber+"\t"+num1+"\t"+num2); Assert.assertTrue(expectedNumber == (Math.substraction(num1, num2))); } @Test public void testAddition2() { Assert.assertEquals(expectedNumber, Math.substraction(num1, num2)); } }
This is test class for Division
package com.junit.suite.example; import static org.junit.Assert.*; import java.util.Arrays; import java.util.List; import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; @RunWith(Parameterized.class) public class DivisionMathTest { int expectedNumber; int num1; int num2; // create a constructor to pass the values public DivisionMathTest(int expectedNumber, int num1, int num2) { // TODO Auto-generated constructor stub this.expectedNumber = expectedNumber; this.num1 = num1; this.num2 = num2; } // create a parameterized method @Parameters public static List<Object[]> createData() { return Arrays.asList(new Object[][] { { 4, 2, 1 }, { 6, 3, 3 }, { 8, 4, 4 } }); } @BeforeClass public static void setUpBeforeClass() throws Exception { } @AfterClass public static void tearDownAfterClass() throws Exception { } @Before public void setUp() throws Exception { } @After public void tearDown() throws Exception { } @Test public void testAddition() { // System.out.println(expectedNumber+"\t"+num1+"\t"+num2); Assert.assertTrue(expectedNumber == (Math.division(num1, num2))); } }
This is where the suite is implemented. All test classes are clubbed together
package com.junit.suite.example; import org.junit.runner.RunWith; import org.junit.runners.Suite; @RunWith(Suite.class) @Suite.SuiteClasses({ AdditionMathTest.class, SubstractionMathTest.class, DivisionMathTest.class }) public class MathTestSuite { }
This is the runner class for suite
package com.junit.suite.example; import java.util.Iterator; import java.util.List; import org.junit.runner.JUnitCore; import org.junit.runner.Result; import org.junit.runner.notification.Failure; public class MathTestRunner { public static void main(String[] args) { Result run = JUnitCore.runClasses(MathTestSuite.class); List<Failure> failures = run.getFailures(); Iterator<Failure> it = failures.iterator(); while (it.hasNext()) { System.out.println(it.next().toString()); } } }
HHH
Sunday, April 17, 2016
Cucumber: BDD BEHAVIOUR DRIVEN TEST
This is a tutorial / technical writing about behaviour driven test (BDD) using Cucumber (Gherkin)
Installing Cucumber -
- Eclipse update site Cucumber - http://cucumber.github.com/cucumber-eclipse/update-site
This plugin is required for creating feature file/ BDD editor
- Cucumber JARs for maven repo http://mvnrepository.com/artifact/info.cukes
Cucumber JVM JUnit
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-junit</artifactId>
<version>1.2.4</version>
</dependency>
Cucumber JVM Java
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-java</artifactId>
<version>1.2.4</version>
</dependency>
Cucumber Core
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-core</artifactId>
<version>1.2.4</version>
</dependency>
BDD - Behaviour Driven Development/ TDD.
The main purpose of BDD is to bridge the gap between the one who is developing the software by actually writing the code and the one who has the idea to have a software which does xyz things.
Using cucumber we write test since the beginning of the project and can have an idea of actually how the software would behave when fully developed in a sense cucumber helps to develop a full set of automated acceptance test.
The main layer of cucumber test suite consists of Feature, Step Definition and Runner class.
The Feature file is where we actually write the test in plain English using a certain set of key words like Give/ When/ Then / And . But these keywords are just for illustration purpose, even if you use any hing arbitrary things would still work without any issue.
Cucumber Feature Files
# Feature file containing scenarios of wordpress login Feature: wordpress blog site login Scenario: perform a successful login with valid credentials Given I am on wordpress login page When I enter valid userName and valid password And I click on the login button Then I am able to login to the wordpress Scenario: perform a login with invalid userName Given I am on wordpress login page When I enter invalid userName and valid password And I click on the login button Then I should get ERROR: Invalid username. Scenario: perform a login with invalid password Given I am on wordpress login page When I enter valid userName and in valid password And I click on the login button Then I should get ERROR: The password you entered for the email address subhra.s.das@gmail.com is incorrect. Scenario: perform a login with invalid userName and invalid password Given I am on wordpress login page When I enter invalid userName and invalid password And I click on the login button Then I should get ERROR: Invalid email address
# Wordpress logout feature Feature: wordpress logout feature Scenario: to check for available links on logout option Given I am on wordpress dashboard page When I mouse hover to the logged in email address Then I get the logged in email address And Edit My Profile link And Logout Option Scenario: to validate a logout action Given I am on wordpress dashboard page When I mouse hover to the logged in email address Then I get logout Option And when i click on logut Then i am logged out And can see message You are now logged out on home page Scenario: to check if sessions get invalidate after logout Given I have performed a successful login When I enter URL http://localhost:8888/wordpress/wp-admin/ directly in browser And Hit enter Then I should be redirected back to home page asking for userName and password
Cucumber Runner Class
The most import annotation used in the runner class is @CucumberOptionsFollowing options are available in cucumber
- Features: path of the feature file or features file in format {"feature_file1","feature_file2"}
- dryRun: by default the value is false. When it is true on those steps on feature file are executed whose steps are converted into step definition. For those in feature file whose steps are not converted as methods ins step definition file are skipped
When dryRun=false every steps in the feature files would be skipped if steps does not have a complete method in step definition class
when dryRun = true
when dryRun = false
- glue: package name where the stepDefinition class resided
- monochrome: for formatting
In valid Gherkin a Feature must be followed by either
- Scenario
- Background
- Scenario Outline
Scenario: starts with description followed by steps which consists of keyword like Given, When, Then, And, But or you can simply ignore these keywords and write test steps using * .
Example
Scenario: perform a successful login with valid credentials
Given I am on wordpress login page
When I enter valid userName and valid password
And I click on the login button
Then I am able to login to the wordpress
When we have repeated steps in every scenario we can take those repeated steps in background
For Example : In this feature file several steps are repeated for every scenario. Instead of repeating this step on each scenario we can take this step on Background section as shown below:
# Feature file for creating new post and editing existing post and moving post to trash Feature: wordpress post functionality of adding post, editing post and deleting post Scenario: to validate add post functionality Given i am on wordpress login page When i enter valid userName and password And click on login Then i login to wordpress successfully And i click on post And click on add new And i add post tilte and post body Then i click on publish to publish a new post Scenario: to validate edit post functionality Given i am on wordpress login page When i enter valid userName and password And click on login Then i login to wordpress successfully And i click on post And i select the post which i need to edit And i click on edit And enter updated details to the post Then i click on update to update and publish the post at the same time Scenario: to validate delete post functionality Given i am on wordpress login page When i enter valid userName and password And click on login Then i login to wordpress successfully And i click on post And i select the post which i need to delete And i select move to trash from dropdown And click on apply
Modified the above feature file using Background
The steps in the background are executed at the beginning of each scenario, just as they were before. What we have done is made each individual scenario much easier to read.
'
Scenario 1: from list and
Scenario 2: from data table
This step definition is for the Feature -> scenario : from list
This step definition is for Feature "From data table"
Step Definition method for data table using Map<String, String>
Step Definition method for data table using List<Map<K,V>>
OUTPUT
The steps in the background are executed at the beginning of each scenario, just as they were before. What we have done is made each individual scenario much easier to read.
'
# Feature file for creating new post and editing existing post and moving post to trash Feature: wordpress post functionality of adding post, editing post and deleting post Backround: description of background section Given i am on wordpress login page When i enter valid userName and password And click on login Then i login to wordpress successfully And i click on post Scenario: to validate add post functionality And click on add new And i add post tilte and post body Then i click on publish to publish a new post Scenario: to validate edit post functionality And i select the post which i need to edit And i click on edit And enter updated details to the post Then i click on update to update and publish the post at the same time Scenario: to validate delete post functionality And i select the post which i need to delete And i select move to trash from dropdown And click on apply
DataDriven Test Using Cucumber
Given example for two scenarioScenario 1: from list and
Scenario 2: from data table
Scenario: from list Given the following users: user1,user2,user3,user4 Scenario: from data table Given i have the following user and password | userName | password | | user_01 | password_01 | | user_02 | password_01 | | user_03 | password_01 |
This step definition is for the Feature -> scenario : from list
@Given("^the following users: (.*)") public void the_following_users_user_user_user_user(List<String> userList) throws Throwable { // Write code here that turns the phrase above into concrete actions // throw new PendingException(); Iterator<String> it = userList.iterator(); while (it.hasNext()) { System.out.println(it.next()); } }
This step definition is for Feature "From data table"
@Given("^i have the following user and password$") public void dataMap01(Map<String, String> userDetails) throws Throwable { // Write // code here that turns the phrase above into concrete actions // For // automatic transformation, change DataTable to one of // List<YourType>, // List<List<E>>, List<Map<K,V>> or Map<K,V>. // E,K,V must be a scalar // (String, Integer, Date, enum etc) // throw new PendingException(); Set<Entry<String, String>> set = userDetails.entrySet(); Iterator<Entry<String, String>> it = set.iterator(); while(it.hasNext()) { Entry<String, String> next = it.next(); System.out.println(next.getKey()); System.out.println(next.getValue()); } }
Step Definition method for data table using List<Map<K,V>>
@Given("^i have the following user and password$") public void dataMap02(List<Map<String, String>> userDetails) throws Throwable { // Write code here that turns the phrase above into concrete actions // For automatic transformation, change DataTable to one of // List<YourType>, List<List<E>>, List<Map<K,V>> or Map<K,V>. // E,K,V must be a scalar (String, Integer, Date, enum etc) // throw new PendingException(); Iterator<Map<String, String>> it = userDetails.iterator(); while (it.hasNext()) { Set<Entry<String, String>> set = it.next().entrySet(); Iterator<Entry<String, String>> mapIt = set.iterator(); while (mapIt.hasNext()) { Entry<String, String> next = mapIt.next(); System.out.println(next.getValue()); System.out.println(next.getKey()); } } }
OUTPUT
# this feature file will illustrate how we can create data # through Gherkin for the purpose of data driven test Feature: generate data like instiantiate the webDriver user1 user2 user3 user4 something like destroying instance of webDriver like instiantiate the webDriver Scenario: from list # /Users/S_Das/Documents/Java/sudas.workspace/CucumberForJava/PageObjectModel/com/sudas/wordpress/BDD/test/data/dataGenerator.feature:5 Given the following users: user1,user2,user3,user4 # DataStepDefinition.the_following_users_user_user_user_user(String>) user_01 userName password_01 password user_02 userName password_01 password user_03 userName password_01 password something like destroying instance of webDriver Scenario: from data table # /Users/S_Das/Documents/Java/sudas.workspace/CucumberForJava/PageObjectModel/com/sudas/wordpress/BDD/test/data/dataGenerator.feature:8 Given i have the following user and password # DataStepDefinition.dataMap02(String,String>>) 2 Scenarios (2 passed) 2 Steps (2 passed) 0m0.131s
For complex data table Scenario
Scenario: create a table with multiple column and retieve data from several columns in step dfinations Given I have the following customer information | firstName | middleName | lastName | dob | userType | password | userName | | sudas | s | das | 22-01-2015 | admin | admin1 | Allen | | sdas | s | das | 15-01-2015 | user | admin2 | Dave | | pdas | | das | 16-01-2015 | user | admin3 | Bob |
Create a user Model class
package com.sudas.wordpress.BDD.test.data.sd; public class UserModel { String firstName; String middleName; String lastName; String dob; String userType; String password; String userName; public UserModel(String firstName, String middleName, String lastName, String dob, String userType, String password, String userName) { super(); this.firstName = firstName; this.middleName = middleName; this.lastName = lastName; this.dob = dob; this.userType = userType; this.password = password; this.userName = userName; } public String getFirstName() { return firstName; } public String getMiddleName() { return middleName; } public String getLastName() { return lastName; } public String getDob() { return dob; } public String getUserType() { return userType; } public String getPassword() { return password; } public String getUserName() { return userName; } }
Now in step definition method get the values like
@Given("^I have the following customer information$") public void i_have_the_following_customer_information(List<UserModel> users) throws Throwable { // Write code here that turns the phrase above into concrete actions // For automatic transformation, change DataTable to one of // List<YourType>, List<List<E>>, List<Map<K,V>> or Map<K,V>. // E,K,V must be a scalar (String, Integer, Date, enum etc) // throw new PendingException(); System.out.println(users.get(0).getFirstName()); System.out.println(users.get(0).getLastName()); System.out.println(users.get(0).getMiddleName()); System.out.println(users.get(0).getUserName()); System.out.println(users.get(0).getPassword()); System.out.println(users.get(0).getUserType()); System.out.println(users.get(0).getDob()); }
OutPut
sudas das s Allen admin1 admin 22-01-2015 something like destroying instance of webDriver Scenario: create a table with multiple column and retieve data from several columns in step dfinations # /Users/S_Das/Documents/Java/sudas.workspace/CucumberForJava/PageObjectModel/com/sudas/wordpress/BDD/test/data/dataGenerator.feature:15 Given I have the following customer information
When to use what
Use of data tableThese steps are replaced by below data table
Given a User "Michael Jackson" born on August 29, 1958 And a User "Elvis" born on January 8, 1935
And a User "John Lennon" born on October 9, 1940
Given these Users:
| name | date of birth |
| Michael Jackson | August 29, 1958 |
| Elvis | January 8, 1935 |
| John Lennon | October 9, 1940 |
Then I should see a vehicle that matches the following description:
| Wheels | 2 |
|MaxSpeed |60mph |
| Accessories | lights, shopping basket |
Then my shopping list should contain: | Onions |
| Potatoes |
| Sausages |
| Apples |
| Relish |
Use Of Scenario Outline
Sometimes you have several scenarios that follow exactly the same pattern of steps, just with different input values or expected outcomes. For example, suppose we are testing the user details for each users. Instead of writing the multiple same scenario with only different set of data the same can be achieved through ScenarioOutline
Scenario Outline: create a table with multiple column and retieve data from several columns in step dfinations Given the userConsole When select the user <UserName> Then the user should belong to company <Company> And the user should belong to company <Org> And the user should belong to company <Department> And the user shoud have the email as <Email> And the user account should not be disabled <IsDisabled> Examples: | UserName | Company | Org | Department | Email | IsDisabled | | User_01 | ABC Corp. | ABC Org | R and D | User_01@abc.com | No | | User_02 | Space X | Space Org | Accounts | User_02@sx.com | No | | User_03 | Speed King | King's Org | Sales | User_03@sk.com | No |
And below is how the method will be implemented
# this feature file will illustrate how we can create data # through Gherkin for the purpose of data driven test Feature: generate data like instiantiate the webDriver user1 user2 user3 user4 something like destroying instance of webDriver like instiantiate the webDriver Scenario: from list # /Users/S_Das/Documents/Java/sudas.workspace/CucumberForJava/PageObjectModel/com/sudas/wordpress/BDD/test/data/dataGenerator.feature:5 Given the following users: user1,user2,user3,user4 # DataStepDefinition.the_following_users_user_user_user_user(String>) user_01 userName password_01 password user_02 userName password_01 password user_03 userName password_01 password something like destroying instance of webDriver like instiantiate the webDriver Scenario: from data table # /Users/S_Das/Documents/Java/sudas.workspace/CucumberForJava/PageObjectModel/com/sudas/wordpress/BDD/test/data/dataGenerator.feature:8 Given i have the following user and password # DataStepDefinition.dataMap02(String,String>>) Subhra Sharanya Pranati something like destroying instance of webDriver Scenario: create a table with multiple column and retieve data from several columns in step dfinations # /Users/S_Das/Documents/Java/sudas.workspace/CucumberForJava/PageObjectModel/com/sudas/wordpress/BDD/test/data/dataGenerator.feature:15 Given I have the following customer information # DataStepDefinition.i_have_the_following_customer_information(UserModel>) Scenario Outline: create a table with multiple column and retieve data from several columns in step dfinations # /Users/S_Das/Documents/Java/sudas.workspace/CucumberForJava/PageObjectModel/com/sudas/wordpress/BDD/test/data/dataGenerator.feature:22 Given the userConsole When select the user <UserName> Then the user should belong to company <Company> And the user should belong to company <Org> And the user should belong to company <Department> And the user shoud have the email as <Email> And the user account should not be disabled <IsDisabled> Examples: like instiantiate the webDriver something like destroying instance of webDriver like instiantiate the webDriver Scenario Outline: create a table with multiple column and retieve data from several columns in step dfinations # /Users/S_Das/Documents/Java/sudas.workspace/CucumberForJava/PageObjectModel/com/sudas/wordpress/BDD/test/data/dataGenerator.feature:33 Given the userConsole When select the user User_01 Then the user should belong to company ABC Corp. And the user should belong to company ABC Org And the user should belong to company R and D And the user shoud have the email as User_01@abc.com And the user account should not be disabled No something like destroying instance of webDriver like instiantiate the webDriver Scenario Outline: create a table with multiple column and retieve data from several columns in step dfinations # /Users/S_Das/Documents/Java/sudas.workspace/CucumberForJava/PageObjectModel/com/sudas/wordpress/BDD/test/data/dataGenerator.feature:34 Given the userConsole When select the user User_02 Then the user should belong to company Space X And the user should belong to company Space Org And the user should belong to company Accounts And the user shoud have the email as User_02@sx.com And the user account should not be disabled No something like destroying instance of webDriver Scenario Outline: create a table with multiple column and retieve data from several columns in step dfinations # /Users/S_Das/Documents/Java/sudas.workspace/CucumberForJava/PageObjectModel/com/sudas/wordpress/BDD/test/data/dataGenerator.feature:35 Given the userConsole When select the user User_03 Then the user should belong to company Speed King And the user should belong to company King's Org And the user should belong to company Sales And the user shoud have the email as User_03@sk.com And the user account should not be disabled No 6 Scenarios (3 undefined, 3 passed) 24 Steps (21 undefined, 3 passed) 0m0.198s You can implement missing steps with the snippets below: @Given("^the userConsole$") public void the_userConsole() throws Throwable { // Write code here that turns the phrase above into concrete actions throw new PendingException(); } @When("^select the user User_(\\d+)$") public void select_the_user_User_(int arg1) throws Throwable { // Write code here that turns the phrase above into concrete actions throw new PendingException(); } @Then("^the user should belong to company ABC Corp\\.$") public void the_user_should_belong_to_company_ABC_Corp() throws Throwable { // Write code here that turns the phrase above into concrete actions throw new PendingException(); } @Then("^the user should belong to company ABC Org$") public void the_user_should_belong_to_company_ABC_Org() throws Throwable { // Write code here that turns the phrase above into concrete actions throw new PendingException(); } @Then("^the user should belong to company R and D$") public void the_user_should_belong_to_company_R_and_D() throws Throwable { // Write code here that turns the phrase above into concrete actions throw new PendingException(); } @Then("^the user shoud have the email as User_(\\d+)@abc\\.com$") public void the_user_shoud_have_the_email_as_User__abc_com(int arg1) throws Throwable { // Write code here that turns the phrase above into concrete actions throw new PendingException(); } @Then("^the user account should not be disabled No$") public void the_user_account_should_not_be_disabled_No() throws Throwable { // Write code here that turns the phrase above into concrete actions throw new PendingException(); } @Then("^the user should belong to company Space X$") public void the_user_should_belong_to_company_Space_X() throws Throwable { // Write code here that turns the phrase above into concrete actions throw new PendingException(); } @Then("^the user should belong to company Space Org$") public void the_user_should_belong_to_company_Space_Org() throws Throwable { // Write code here that turns the phrase above into concrete actions throw new PendingException(); } @Then("^the user should belong to company Accounts$") public void the_user_should_belong_to_company_Accounts() throws Throwable { // Write code here that turns the phrase above into concrete actions throw new PendingException(); } @Then("^the user shoud have the email as User_(\\d+)@sx\\.com$") public void the_user_shoud_have_the_email_as_User__sx_com(int arg1) throws Throwable { // Write code here that turns the phrase above into concrete actions throw new PendingException(); } @Then("^the user should belong to company Speed King$") public void the_user_should_belong_to_company_Speed_King() throws Throwable { // Write code here that turns the phrase above into concrete actions throw new PendingException(); } @Then("^the user should belong to company King's Org$") public void the_user_should_belong_to_company_King_s_Org() throws Throwable { // Write code here that turns the phrase above into concrete actions throw new PendingException(); } @Then("^the user should belong to company Sales$") public void the_user_should_belong_to_company_Sales() throws Throwable { // Write code here that turns the phrase above into concrete actions throw new PendingException(); } @Then("^the user shoud have the email as User_(\\d+)@sk\\.com$") public void the_user_shoud_have_the_email_as_User__sk_com(int arg1) throws Throwable { // Write code here that turns the phrase above into concrete actions throw new PendingException(); }
Hello World
Subscribe to:
Posts (Atom)