Testing Debugging Loggig Performance Tuning Struts Applications

  • Uploaded by: Adarsh
  • 0
  • 0
  • May 2020
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Testing Debugging Loggig Performance Tuning Struts Applications as PDF for free.

More details

  • Words: 2,794
  • Pages: 79
Testing, Debugging, Logging, Performance tuning Struts Applications 1

Sang Shin [email protected] www.javapassion.com Java™ Technology Evangelist Sun Microsystems, Inc. 2

Disclaimer & Acknowledgments ●





Even though Sang Shin is a full-time employees of Sun Microsystems, the contents here are created as their own personal endeavor and thus does not reflect any official stance of Sun Microsystems. Sun Microsystems is not responsible for any inaccuracies in the contents. Acknowledgments: –

The slides from this presentation is made from StrutsTestCase tutorial from http://strutstestcase.sourceforge.net/ written by Deryl Seale

3

Revision History ● ●

12/01/2003: version 1: created by Sang Shin Things to do – Contents on performance tuning, debugging still need to be added

4

Topics ● ● ● ● ● ●

Unit testing with StrutsTestCase Use case scenario testing with JWebUnit Logging with Commons Logging & Log4J Debugging Performance testing with JUnitPerf Coverage testing with jCoverage

5

Unit Testing with StrutsTestCase 6

Unit Testing Tools ●

JUnit – –



Cactus – –



For testing Java class http://www.junit.org For testing JSP, taglibs and conventional servlet components http://jakarta.apache.org/cactus/

StrutsTestCase – –

For testing Action classes http://strutstestcase.sourceforge.net 7

StrutsTestCase ●





Extends JUnit framework to allow testing the Action class Because StrutsTestCase uses the ActionServlet controller to test your code, you can test not only the implementation of your Action objects, but also your mappings, form beans, and forwards declarations Offers two approaches for testing – –

Mock Object approach In-container testing approach

8

Two Testing Approaches ●

Mock objects approach –



In-container testing approach –



test classes by simulating the server container tests classes running in the actual server container

StrutsTestCase for JUnit allows you to use either approach, with very minimal impact on your actual unit test code – –

setup and validation methods are exactly the same for both approaches choosing one approach over the other simply effects which base class you use 9

Base Classes ●

Mock objects –



MockStrutsTestCase uses a set of HttpServlet mock objects to simulate the container environment without requiring a running servlet engine

In-container –

CactusStrutsTestCase uses the Cactus testing framework to test Struts classes in the actual server container

10

Example Action Class To Be Tested public class LoginAction extends Action { public ActionForward perform(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response){ String username = ((LoginForm) form).getUsername(); String password = ((LoginForm) form).getPassword(); ActionErrors errors = new ActionErrors(); if ((!username.equals("deryl")) || (!password.equals("radar"))) errors.add("password",new ActionError("error.password.mismatch")); if (!errors.empty()) { saveErrors(request,errors); return mapping.findForward("login"); } 11

Example Action Class To Be Tested // store authentication info on the session HttpSession session = request.getSession(); session.setAttribute("authentication", username); // Forward control to the specified success URI return mapping.findForward("success"); }

12

Things That Can to be Tested for the LoginAction ●

ActionForm related – –



Does the LoginForm bean work properly? If we place the appropriate parameters in the request, does this bean get instantiated correctly?

Error condition handling –



If the username or password doesn't match, do the appropriate errors get saved for display on the next screen? Are we sent back to the login page? 13

Things That Can to be Tested for the LoginAction (Continued) ●

Expected behavior – – –

If we supply the correct login information, do we get to the correct page? Are we sure there are no errors reported? Does the proper authentication information get saved in the session?

14

Example: Empty Test Case public class TestLoginAction extends MockStrutsTestCase { public void setUp() { super.setUp(); } public void tearDown() { super.tearDown(); } public TestLoginAction(String testName) { super(testName); } public void testSuccessfulLogin() {} }

15

Step By Step Procedure using StrutsTestCase 16

struts-config.xml <struts-config> 17

web.xml <servlet> <servlet-name>action <servlet-class>org.apache.struts.action.ActionServlet <param-name>application <param-value>examples.ApplicationResources <param-name>config <param-value>/WEB-INF/struts-config.xml <param-name>config/tiles <param-value>/WEB-INF/struts-config-tiles.xml <param-name>config/test <param-value>/WEB-INF/struts-config-test.xml 18

LoginAction public class LoginAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { String username = ((LoginForm) form).getUsername(); String password = ((LoginForm) form).getPassword(); ActionErrors errors = new ActionErrors(); if ((!username.equals("deryl")) || (!password.equals("radar"))) errors.add("password",new ActionError("error.password.mismatch")); if (!errors.isEmpty()) { saveErrors(request,errors); return new ActionForward(mapping.getInput()); }

19

LoginAction HttpSession session = request.getSession(); session.setAttribute("authentication", username); // Forward control to the specified success URI return mapping.findForward("success"); } }

20

Step 1: Tell Struts which mapping to use in this test public class TestLoginAction extends MockStrutsTestCase { public TestLoginAction(String testName) { super(testName); } public void testSuccessfulLogin() { // Tell Struts which mapping to use in this test. // To do so, we specify a path that is associated with // a Struts mapping; this is the same mechanism that // the Struts tag library method uses. setRequestPathInfo("/login"); } }

21

Step 2: Pass Form Bean Parameters public class TestLoginAction extends MockStrutsTestCase { public TestLoginAction(String testName) { super(testName); } public void testSuccessfulLogin() { setRequestPathInfo("/login"); // pass form bean parameters addRequestParameter("username","deryl"); addRequestParameter("password","radar"); } }

22

Step 3: Make Action Class do its work public class TestLoginAction extends MockStrutsTestCase { public TestLoginAction(String testName) { super(testName); } public void testSuccessfulLogin() { setRequestPathInfo("/login"); addRequestParameter("username","deryl"); addRequestParameter("password","radar"); // Make the Action to do its thing, which just involves // executing the actionPerform method actionPerform(); } }

23

Step 4: Verify that everything happened as expected public class TestLoginAction extends MockStrutsTestCase { public TestLoginAction(String testName) { super(testName); } public void testSuccessfulLogin() { setRequestPathInfo("/login"); addRequestParameter("username","deryl"); addRequestParameter("password","radar"); actionPerform(); // verify that everything happened as we expected it to verifyForward("success"); } }

24

Step 5: Make sure that authentication information was stored properly: public class TestLoginAction extends MockStrutsTestCase { public TestLoginAction(String testName) { super(testName); } public void testSuccessfulLogin() { setRequestPathInfo("/login"); addRequestParameter("username","deryl"); addRequestParameter("password","radar"); actionPerform(); verifyForward("success"); // Make sure that authentication information was stored properly assertEquals("deryl",(String) getSession().getAttribute("authentication")); } }

25

Step 6: Verify No ActionError messages were sent along public class TestLoginAction extends MockStrutsTestCase { public TestLoginAction(String testName) { super(testName); } public void testSuccessfulLogin() { setRequestPathInfo("/login"); addRequestParameter("username","deryl"); addRequestParameter("password","radar"); actionPerform(); verifyForward("success"); assertEquals("deryl",(String) getSession().getAttribute("authentication")); // Make sure that no ActionError messages were sent along. // We can use a built in method to make sure of this condition: verifyNoActionErrors(); } } 26

Example 2: test the case where a user supplies incorrect login information public class TestLoginAction extends MockStrutsTestCase { public TestLoginAction(String testName) { super(testName); } public void testSuccessfulLogin() { addRequestParameter("username","deryl"); addRequestParameter("password","express"); setRequestPathInfo("/login"); actionPerform(); // Test the case where a user supplies incorrect login information verifyForward("login"); verifyActionErrors(new String[] {"error.password.mismatch"}); assertNull((String) getSession().getAttribute("authentication")); } }

27

Verification Methods 28

StrutsTestCase Verification Methods ● ● ● ● ● ● ●

verify[No]ActionErrors verify[No]ActionMessages verifyForward verifyForwardPath verifyInputForward verifyTilesForward verifyInputTilesForward 29

Testing Tiles using StrutsTestCase 30

Test If Correct Tile Definition is Used for Forwarding public class TestLoginAction extends MockStrutsTestCase { public TestLoginAction(String testName) { super(testName); } public void testSuccessfulLogin() { setConfigFile("/WEB-INF/struts-config.xml"); setRequestPathInfo("/login.do"); addRequestParameter("username","deryl"); addRequestParameter("password","radar"); actionPerform(); verifyTilesForward("success","success.tiles.def"); } }

31

Lab Exercise ●



http://www.javapassion.com/handsonlabs/4 220_strutstestcase.zip Unzip in a directory and read strutstestcase/index.html to proceed

32

Use Case Scenario Testing with jWebUnit

33

jWebUnit Testing Framework ●

Allows testing of a Web application through use case scenarios –



Exercises a running Web application by programmatically sending requests, clicking links, filling out and submitting forms, and inspecting the response

Based on – –

JUnit: provides testing harness and basic assertion methods HttpUnit: provides a mechanism for programmatically sending requests and reading responses from a Web application

34

How to Create new jWebUnit Test Class? ●

Extend net.sourceforge.jwebunit.WebTestCase class

35

What Does jWebUnit Provide? ●

jWebUnit provides a high-level API for navigating a web application combined with a set of assertions to verify the application's correctness – – – –



navigation via links form entry and submission validation of table contents other typical business web application features

More effective than using JUnit and HTTPUnit alone

36

Test Scenario ●

● ●

Perform a google search for the HttpUnit home page then Navigate to that page from Google and Validate that there is a link to the user manual on the HttpUnit home page

37

jWebUnit Code package net.sourceforge.jwebunit.sample; import net.sourceforge.jwebunit.WebTestCase; public class JWebUnitSearchExample extends WebTestCase { public JWebUnitSearchExample(String name) { super(name); } public void setUp() { getTestContext().setBaseUrl("http://www.google.com"); } public void testSearch() { beginAt("/"); setFormElement("q", "httpunit"); submit("btnG"); clickLinkWithText("HttpUnit"); assertTitleEquals("HttpUnit"); assertLinkPresentWithText("User's Manual"); }

38

JUnit and HTTPUnit Code package net.sourceforge.jwebunit.sample; import junit.framework.TestCase; import com.meterware.httpunit.WebResponse; import com.meterware.httpunit.WebConversation; import com.meterware.httpunit.WebForm; import com.meterware.httpunit.WebRequest; public class SearchExample extends TestCase { public void testSearch() throws Exception { WebConversation wc = new WebConversation(); WebResponse resp = wc.getResponse( "http://www.google.com"); WebForm form = resp.getForms()[0]; form.setParameter("q", "HttpUnit"); WebRequest req = form.getRequest("btnG"); resp = wc.getResponse(req); assertNotNull(resp.getLinkWith("HttpUnit")); resp = resp.getLinkWith("HttpUnit").click(); assertEquals(resp.getTitle(), "HttpUnit"); assertNotNull(resp.getLinkWith("User's Manual")); }

39

Lab: JWebUnit ●

I will show you in the class

40

Logging with Commons Logging & Log4J

41

Logging Schemes for Web Applications ●

Using log() method of ServletConext object – –



Comes with J2EE Simple but primitive

Jakarta commons logging –

Highly flexible and sophisticated logging scheme

42

Log() method of ServletContext ●





Every container has to support this method of logging Name and location of the log file is container specific ServletContext class has two log() methods – –

public void log (String msg); public void log (String msg, Throwable throwable);

43

Commons Logging 44

What is Jakarta Commons Logging? ●

Provides common logging API –



Insulates applications from actual logging implementations –



API has no dependency to any logging implementations

Applications do not have to change when logging implementation is changed

Developers declaratively configure logging implementation –

Logging implementation is dynamically discovered at runtime

45

Possible Logging Implementations ●

Log4J – –



http://logging.apache.org/log4j/ Popular open source logging solution

JDK 1.4 logging –

Built-in in J2SE

46

Log4J 47

Log4J Configuration ● ●

Reads its setting from log4j.properties file Classes write logging messages using logger –



The logger matches fully qualified class or package name

Loggers hierarchical – –

log4j.logger.org.apache.struts=DEBUG,Console,File log4j.logger.org.apache.struts.action=DEBUG,Console

48

Log4J Configuration: Logger ●

For each logger, you can set –

Logging level ● ● ● ● ● ●

– ●

Trace Debug Infro Warn Error Fatal

Appenders (Destinations of the log messages)

Example: –

log4j.logger.org.apache.struts=DEBUG,Console,File 49

Log4J Configuration: Appender ●

Appenders are configured using log4j.appender property – –



Appender class Layout pattern

Example – – –

log4j.appender.Console=org.apache.log4j.ConsoleAppender log4j.appender.Console.layout=org.apache.log4j.PatternLayout log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p %c - %m%n ● %d: date, %t: thread ●

%-5p: priority, %c: class name



%m: log message, %n: carrige return 50

Example:log4j.properties # The output information consists of relative time, log level, thread # name, logger name, nested diagnostic context and the message in that # order. # For the general syntax of property based configuration files see the # documenation of org.apache.log4j.PropertyConfigurator. log4j.rootLogger=WARN,Console log4j.logger.org.apache.struts=DEBUG,Console #log4j.logger.servletunit=DEBUG,Console #log4j.logger.com.jadecove=DEBUG,Console #log4j.logger.org.apache.struts=WARN,Console log4j.appender.Console=org.apache.log4j.ConsoleAppender log4j.appender.Console.layout=org.apache.log4j.PatternLayout log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p %c - %m%n

51

Example:log4j.properties # A1 is set to be a FileAppender which outputs to facet.log log4j.appender.A1=org.apache.log4j.FileAppender log4j.appender.A1.file=facet.log # A1 uses PatternLayout. log4j.appender.A1.layout=org.apache.log4j.PatternLayout # The conversion pattern uses format specifiers. You might want to # change the pattern an watch the output format change. log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n

52

How To Configure Commons Logging with Log4J ●

Create commons-logging.properties file and save it under your applications WEBINF/classes directory –



org.apache.commons.logging.LogFactory=org.apa che.commons.logging.impl.Log4jFactory

Create log4j.properties file and save it under your applications WEB-INF/classes directory

53

Adding Logging to Your Own Class 54

Example: How to Use Logging API? import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public final class EditSubscriptionAction extends Action { private Log log = LogFactory.getLog("org.apache.struts.webapp.Example"); public ActionForward execute(ActionMapping mapping, ..) throw Exception{ .... if (log.isDebugEnabled()) { log.debug("EditSubscriptionAction: Processing " + action + " action"); } .... if (user == null) { if (log.isTraceEnabled()) { log.trace(" User is not logged on in session " + session.getId()); } return (mapping.findForward("logon")); }

55

Example2: init() method of MemoryDatabasePlugin in struts-example1 public final class MemoryDatabasePlugIn implements PlugIn { ... /** * Initialize and load our initial database from persistent storage. * * @param servlet The ActionServlet for this web application * @param config The ApplicationConfig for our owning module * * @exception ServletException if we cannot configure ourselves correctly */ public void init(ActionServlet servlet, ModuleConfig config) throws ServletException { log.info("Initializing memory database plug in from '" + pathname + "'"); // Remember our associated configuration and servlet this.config = config; this.servlet = servlet; 56

Example2: init() method of MemoryDatabasePlugin in struts-example1

57

<jwsdp-install>/logs/launcher.server.log

58

Lab: Configuring Struts Logging ● ●

ch 13.2 (page 407) To do – – –

Clear Tomcat log output Run the application See the logging messages from Struts framework

59

Lab: Adding Logging to Your Class ● ●

ch 13.3 (page 409) To do – – –

See MyClazz.java file See log4j.properties file Modify log4j.properties file to display debug messages from the application

60

Debugging

61

Lab: TroubleShooting JSP Pages ● ●

Ch 13.5 (page 414) For running –



Click “Register with the MailReader Demonstration Application” and see the display

For exploring –

Check how debug.jsp page is included in Registration.jsp page

62

Performance Testing with JUnitPerf

63

Performance Test ●

Timed test –



Load test –



ensures that a single test run by a single user executes within a time limit measures the application responsiveness by repeatedly executing tests with a predefined number of concurrent users

Throughput test –

measures the number of requests executed within a given period of time 64

Performance Test ●

Response-time-under-load test –



ensures each unit test meets a performance expectation while under load

Burst test –

a variation of a load test that spikes the load between two periods of normal load

65

Why JUnitPerf? ●

transparently decorate existing JUnit tests –



performance testing to be dynamically added to an existing JUnit test without affecting the use of the JUnit test independent of its performance

performance test suite can then be run automatically and independent of your other JUnit tests –

you can run the test suites independently and at different frequencies 66

Usage Examples ●



You might write a JUnitPerf test to ensure that refactoring an algorithm didn't incur undesirable performance overhead in a performance-critical code section You might also write a JUnitPerf test to ensure that refactoring a resource pool didn't adversely affect the scalability of the pool under load.

67

Usage Approach ●



Traditional performance profiling tools and techniques should be employed first to identify which areas of code exhibit the highest potential for performance and scalability problems JUnitPerf tests can then be written to automatically test and check that requirements are being met now and in the future. 68

TimedTest Example 1 ●

To create a timed test that waits for the completion of the ExampleTestCase.testOneSecondResponse() method and then fails if the elapsed time exceeded 1 second, use: long maxElapsedTime = 1000; Test testCase = new ExampleTestCase ("testOneSecondResponse"); Test timedTest = new TimedTest(testCase, maxElapsedTime); 69

TimedTest Example 2 ●

To create a timed test that fails immediately when the elapsed time of the ExampleTestCase.testOneSecondResponse() test method exceeds 1 second, use:

long maxElapsedTime = 1000; Test testCase = new ExampleTestCase ("testOneSecondResponse"); Test timedTest = new TimedTest(testCase, maxElapsedTime, false); 70

LoadTest Example 1 ●

To create a load test of 10 concurrent users with each user running the ExampleTestCase.testOneSecondResponse() method once and all users starting simultaneously, use: int users = 10; Test testCase = new ExampleTestCase ("testOneSecondResponse"); Test loadTest = new LoadTest(testCase, users); 71

LoadTest Example 2 ●

To create a load test of 10 concurrent users with each user running the ExampleTestCase.testOneSecondResponse() method once and with a 1 second delay between the addition of users, use: int users = 10; Timer timer = new ConstantTimer(1000); Test testCase = new ExampleTestCase ("testOneSecondResponse"); Test loadTest = new LoadTest(testCase, users, timer);

72

LoadTest Example 3 ●

To create a load test of 10 concurrent users with each user running the ExampleTestCase.testOneSecondResponse() method for 20 iterations, and with a 1 second delay between the addition of users, use: int users = 10; int iterations = 20; Timer timer = new ConstantTimer(1000); Test testCase = new ExampleTestCase ("testOneSecondResponse"); Test repeatedTest = new RepeatedTest(testCase, iterations); Test loadTest = new LoadTest(repeatedTest, users, timer); 73

Commercial Performance Tools ● ●

Sitraka PerformanceSure Borland OptimizeIt

74

Lab: JUnitPerf ●

● ●

Unzip the junitperf-1.9.1.zip in a directory of your choice cd junitperf-1.9.1 ant

75

Coverage Testing with jCoverage

76

jCoverage ●





Test the coverage of your code by inserting instrumentation instructions directly into your compiled Java classes When these instructions are encountered by the Java Virtual Machine, the inserted code increments various counters so that it is possible to tell which instructions have been encountered and which have not Works with Ant 77

jCoverage Works With Ant ●

Select the files to be instrumented

78

Passion!

79

Related Documents


More Documents from ""